summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am11
-rw-r--r--plugins/apihashing/Makefile.am65
-rw-r--r--plugins/apihashing/apihash.c134
-rw-r--r--plugins/apihashing/apihash.h55
-rw-r--r--plugins/apihashing/classics/Makefile.am14
-rw-r--r--plugins/apihashing/classics/crc32.c332
-rw-r--r--plugins/apihashing/classics/crc32.h58
-rw-r--r--plugins/apihashing/classics/djb2.c323
-rw-r--r--plugins/apihashing/classics/djb2.h58
-rw-r--r--plugins/apihashing/classics/ror13.c323
-rw-r--r--plugins/apihashing/classics/ror13.h58
-rw-r--r--plugins/apihashing/core.c110
-rw-r--r--plugins/apihashing/core.h38
-rw-r--r--plugins/apihashing/custom/Makefile.am18
-rw-r--r--plugins/apihashing/custom/add1505-shl5.c325
-rw-r--r--plugins/apihashing/custom/add1505-shl5.h58
-rw-r--r--plugins/apihashing/custom/enigma-murmur.c377
-rw-r--r--plugins/apihashing/custom/enigma-murmur.h58
-rw-r--r--plugins/apihashing/custom/imul21-add.c326
-rw-r--r--plugins/apihashing/custom/imul21-add.h58
-rw-r--r--plugins/apihashing/custom/imul83-add.c326
-rw-r--r--plugins/apihashing/custom/imul83-add.h58
-rw-r--r--plugins/apihashing/custom/sll1-add-hash32.c326
-rw-r--r--plugins/apihashing/custom/sll1-add-hash32.h58
-rw-r--r--plugins/apihashing/custom/sub-index1.c291
-rw-r--r--plugins/apihashing/custom/sub-index1.h58
-rw-r--r--plugins/apihashing/custom/sub42.c291
-rw-r--r--plugins/apihashing/custom/sub42.h58
-rw-r--r--plugins/apihashing/python/Makefile.am20
-rw-r--r--plugins/apihashing/python/apihash.c212
-rw-r--r--plugins/apihashing/python/apihash.h45
-rw-r--r--plugins/apihashing/python/classics/Makefile.am16
-rw-r--r--plugins/apihashing/python/classics/crc32.c211
-rw-r--r--plugins/apihashing/python/classics/crc32.h45
-rw-r--r--plugins/apihashing/python/classics/djb2.c211
-rw-r--r--plugins/apihashing/python/classics/djb2.h45
-rw-r--r--plugins/apihashing/python/classics/module.c68
-rw-r--r--plugins/apihashing/python/classics/module.h38
-rw-r--r--plugins/apihashing/python/classics/ror13.c211
-rw-r--r--plugins/apihashing/python/classics/ror13.h45
-rw-r--r--plugins/apihashing/python/custom/Makefile.am20
-rw-r--r--plugins/apihashing/python/custom/add1505-shl5.c211
-rw-r--r--plugins/apihashing/python/custom/add1505-shl5.h45
-rw-r--r--plugins/apihashing/python/custom/enigma-murmur.c211
-rw-r--r--plugins/apihashing/python/custom/enigma-murmur.h45
-rw-r--r--plugins/apihashing/python/custom/imul21-add.c211
-rw-r--r--plugins/apihashing/python/custom/imul21-add.h45
-rw-r--r--plugins/apihashing/python/custom/imul83-add.c211
-rw-r--r--plugins/apihashing/python/custom/imul83-add.h45
-rw-r--r--plugins/apihashing/python/custom/module.c76
-rw-r--r--plugins/apihashing/python/custom/module.h38
-rw-r--r--plugins/apihashing/python/custom/sll1-add-hash32.c211
-rw-r--r--plugins/apihashing/python/custom/sll1-add-hash32.h45
-rw-r--r--plugins/apihashing/python/custom/sub-index1.c213
-rw-r--r--plugins/apihashing/python/custom/sub-index1.h45
-rw-r--r--plugins/apihashing/python/custom/sub42.c212
-rw-r--r--plugins/apihashing/python/custom/sub42.h45
-rw-r--r--plugins/apihashing/python/module.c87
-rw-r--r--plugins/apihashing/python/module.h38
-rw-r--r--plugins/arm/Makefile.am33
-rw-r--r--plugins/arm/core.c7
-rw-r--r--plugins/arm/instruction.c121
-rw-r--r--plugins/arm/python/Makefile.am16
-rw-r--r--plugins/arm/python/instruction.c12
-rw-r--r--plugins/arm/python/processor.c9
-rw-r--r--plugins/arm/python/v7/Makefile.am15
-rw-r--r--plugins/arm/python/v7/instruction.c11
-rw-r--r--plugins/arm/python/v7/processor.c10
-rw-r--r--plugins/arm/register.c97
-rw-r--r--plugins/arm/v7/Makefile.am43
-rw-r--r--plugins/arm/v7/instruction.c109
-rw-r--r--plugins/arm/v7/opcodes/Makefile.am7
-rw-r--r--plugins/arm/v7/operand-int.h51
-rw-r--r--plugins/arm/v7/operand.c188
-rw-r--r--plugins/arm/v7/operand.h55
-rw-r--r--plugins/arm/v7/operands/Makefile.am27
-rw-r--r--plugins/arm/v7/operands/estate.c178
-rw-r--r--plugins/arm/v7/operands/estate.h11
-rw-r--r--plugins/arm/v7/operands/iflags.c179
-rw-r--r--plugins/arm/v7/operands/iflags.h10
-rw-r--r--plugins/arm/v7/operands/it.c333
-rw-r--r--plugins/arm/v7/operands/limitation.c271
-rw-r--r--plugins/arm/v7/operands/maccess.c530
-rw-r--r--plugins/arm/v7/operands/maccess.h9
-rw-r--r--plugins/arm/v7/operands/offset.c280
-rw-r--r--plugins/arm/v7/operands/offset.h11
-rw-r--r--plugins/arm/v7/operands/register.c279
-rw-r--r--plugins/arm/v7/operands/register.h12
-rw-r--r--plugins/arm/v7/operands/reglist.c331
-rw-r--r--plugins/arm/v7/operands/rotation.c231
-rw-r--r--plugins/arm/v7/operands/shift.c335
-rw-r--r--plugins/arm/v7/registers/Makefile.am17
-rw-r--r--plugins/arm/v7/registers/banked.c68
-rw-r--r--plugins/arm/v7/registers/basic.c68
-rw-r--r--plugins/arm/v7/registers/coproc.c68
-rw-r--r--plugins/arm/v7/registers/simd.c181
-rw-r--r--plugins/arm/v7/registers/special.c68
-rw-r--r--plugins/bhash/Makefile.am8
-rw-r--r--plugins/bhash/core.c7
-rw-r--r--plugins/bhash/python/Makefile.am17
-rw-r--r--plugins/bootimg/Makefile.am16
-rw-r--r--plugins/bootimg/core.c7
-rw-r--r--plugins/bootimg/format-int.h2
-rw-r--r--plugins/bootimg/python/Makefile.am15
-rw-r--r--plugins/bootimg/python/format.c7
-rw-r--r--plugins/dalvik/Makefile.am39
-rw-r--r--plugins/dalvik/context.c4
-rw-r--r--plugins/dalvik/context.h2
-rw-r--r--plugins/dalvik/core.c7
-rw-r--r--plugins/dalvik/operand.c2
-rw-r--r--plugins/dalvik/operands/Makefile.am16
-rw-r--r--plugins/dalvik/operands/args.c321
-rw-r--r--plugins/dalvik/operands/pool.c416
-rw-r--r--plugins/dalvik/pseudo/Makefile.am13
-rw-r--r--plugins/dalvik/python/Makefile.am16
-rw-r--r--plugins/dalvik/python/instruction.c5
-rw-r--r--plugins/dalvik/python/processor.c5
-rw-r--r--plugins/dalvik/python/v35/Makefile.am15
-rw-r--r--plugins/dalvik/python/v35/instruction.c5
-rw-r--r--plugins/dalvik/python/v35/processor.c5
-rw-r--r--plugins/dalvik/register.c197
-rw-r--r--plugins/dalvik/register.h3
-rw-r--r--plugins/dalvik/v35/Makefile.am17
-rw-r--r--plugins/dalvik/v35/opcodes/Makefile.am7
-rw-r--r--plugins/devdbg/Makefile.am9
-rw-r--r--plugins/dex/Makefile.am28
-rw-r--r--plugins/dex/core.c7
-rw-r--r--plugins/dex/loading.h4
-rw-r--r--plugins/dex/pool.c35
-rw-r--r--plugins/dex/python/Makefile.am27
-rw-r--r--plugins/dex/python/class.c6
-rw-r--r--plugins/dex/python/field.c6
-rw-r--r--plugins/dex/python/format.c5
-rw-r--r--plugins/dex/python/method.c6
-rw-r--r--plugins/dex/python/pool.c2
-rw-r--r--plugins/dex/python/routine.c5
-rw-r--r--plugins/dexbnf/Makefile.am20
-rw-r--r--plugins/dexbnf/core.c9
-rw-r--r--plugins/dexbnf/demangler.c27
-rw-r--r--plugins/dexbnf/python/Makefile.am13
-rw-r--r--plugins/dexbnf/python/demangler.c10
-rw-r--r--plugins/dwarf/Makefile.am30
-rw-r--r--plugins/dwarf/core.c3
-rw-r--r--plugins/dwarf/info.h1
-rw-r--r--plugins/dwarf/v2/Makefile.am9
-rw-r--r--plugins/dwarf/v3/Makefile.am9
-rw-r--r--plugins/dwarf/v4/Makefile.am9
-rw-r--r--plugins/elf/Makefile.am32
-rw-r--r--plugins/elf/core.c7
-rw-r--r--plugins/elf/loading.h2
-rw-r--r--plugins/elf/python/Makefile.am25
-rw-r--r--plugins/elf/python/format.c12
-rw-r--r--plugins/elf/strings.h2
-rw-r--r--plugins/elf/symbols.h2
-rw-r--r--plugins/encodings/Makefile.am64
-rw-r--r--plugins/encodings/base64.c139
-rw-r--r--plugins/encodings/base64.h43
-rw-r--r--plugins/encodings/core.c89
-rw-r--r--plugins/encodings/core.h38
-rw-r--r--plugins/encodings/python/Makefile.am21
-rw-r--r--plugins/encodings/python/base64.c139
-rw-r--r--plugins/encodings/python/base64.h39
-rw-r--r--plugins/encodings/python/module.c87
-rw-r--r--plugins/encodings/python/module.h38
-rw-r--r--plugins/encodings/python/rost/Makefile.am15
-rw-r--r--plugins/encodings/python/rost/base64.c211
-rw-r--r--plugins/encodings/python/rost/base64.h45
-rw-r--r--plugins/encodings/python/rost/module.c64
-rw-r--r--plugins/encodings/python/rost/module.h38
-rw-r--r--plugins/encodings/rost/Makefile.am12
-rw-r--r--plugins/encodings/rost/base64.c555
-rw-r--r--plugins/encodings/rost/base64.h58
-rw-r--r--plugins/fmtp/Makefile.am11
-rw-r--r--plugins/gdbrsp/python/gdb.c5
-rw-r--r--plugins/itanium/Makefile.am20
-rw-r--r--plugins/itanium/core.c9
-rw-r--r--plugins/itanium/demangler.c27
-rw-r--r--plugins/itanium/python/Makefile.am13
-rw-r--r--plugins/itanium/python/demangler.c10
-rw-r--r--plugins/java/Makefile.am7
-rw-r--r--plugins/javadesc/Makefile.am18
-rw-r--r--plugins/javadesc/core.c9
-rw-r--r--plugins/javadesc/demangler.c27
-rw-r--r--plugins/javadesc/python/Makefile.am13
-rw-r--r--plugins/javadesc/python/demangler.c10
-rw-r--r--plugins/kaitai/Makefile.am93
-rw-r--r--plugins/kaitai/array-int.h51
-rw-r--r--plugins/kaitai/array.c376
-rw-r--r--plugins/kaitai/array.h76
-rw-r--r--plugins/kaitai/core.c81
-rw-r--r--plugins/kaitai/core.h38
-rw-r--r--plugins/kaitai/expression.h134
-rw-r--r--plugins/kaitai/grammar.y1919
-rw-r--r--plugins/kaitai/import.c300
-rw-r--r--plugins/kaitai/import.h41
-rw-r--r--plugins/kaitai/parser-int.h55
-rw-r--r--plugins/kaitai/parser.c166
-rw-r--r--plugins/kaitai/parser.h63
-rw-r--r--plugins/kaitai/parsers/Makefile.am25
-rw-r--r--plugins/kaitai/parsers/attribute-int.h107
-rw-r--r--plugins/kaitai/parsers/attribute.c2213
-rw-r--r--plugins/kaitai/parsers/attribute.h158
-rw-r--r--plugins/kaitai/parsers/enum-int.h79
-rw-r--r--plugins/kaitai/parsers/enum.c765
-rw-r--r--plugins/kaitai/parsers/enum.h76
-rw-r--r--plugins/kaitai/parsers/instance-int.h59
-rw-r--r--plugins/kaitai/parsers/instance.c503
-rw-r--r--plugins/kaitai/parsers/instance.h71
-rw-r--r--plugins/kaitai/parsers/meta-int.h60
-rw-r--r--plugins/kaitai/parsers/meta.c (renamed from plugins/yaml/line.c)325
-rw-r--r--plugins/kaitai/parsers/meta.h71
-rw-r--r--plugins/kaitai/parsers/struct-int.h77
-rw-r--r--plugins/kaitai/parsers/struct.c837
-rw-r--r--plugins/kaitai/parsers/struct.h80
-rw-r--r--plugins/kaitai/parsers/switch-int.h78
-rw-r--r--plugins/kaitai/parsers/switch.c644
-rw-r--r--plugins/kaitai/parsers/switch.h61
-rw-r--r--plugins/kaitai/parsers/type-int.h58
-rw-r--r--plugins/kaitai/parsers/type.c (renamed from plugins/yaml/reader.c)276
-rw-r--r--plugins/kaitai/parsers/type.h65
-rw-r--r--plugins/kaitai/python/Makefile.am26
-rw-r--r--plugins/kaitai/python/array.c265
-rw-r--r--plugins/kaitai/python/array.h45
-rw-r--r--plugins/kaitai/python/module.c135
-rw-r--r--plugins/kaitai/python/module.h41
-rw-r--r--plugins/kaitai/python/parser.c205
-rw-r--r--plugins/kaitai/python/parser.h (renamed from plugins/yaml/python/reader.h)18
-rw-r--r--plugins/kaitai/python/parsers/Makefile.am19
-rw-r--r--plugins/kaitai/python/parsers/attribute.c425
-rw-r--r--plugins/kaitai/python/parsers/attribute.h45
-rw-r--r--plugins/kaitai/python/parsers/enum.c468
-rw-r--r--plugins/kaitai/python/parsers/enum.h45
-rw-r--r--plugins/kaitai/python/parsers/instance.c280
-rw-r--r--plugins/kaitai/python/parsers/instance.h45
-rw-r--r--plugins/kaitai/python/parsers/meta.c414
-rw-r--r--plugins/kaitai/python/parsers/meta.h (renamed from plugins/yaml/python/scalar.h)18
-rw-r--r--plugins/kaitai/python/parsers/module.c124
-rw-r--r--plugins/kaitai/python/parsers/module.h41
-rw-r--r--plugins/kaitai/python/parsers/struct.c376
-rw-r--r--plugins/kaitai/python/parsers/struct.h45
-rw-r--r--plugins/kaitai/python/parsers/type.c278
-rw-r--r--plugins/kaitai/python/parsers/type.h45
-rw-r--r--plugins/kaitai/python/record.c (renamed from plugins/yaml/python/line.c)338
-rw-r--r--plugins/kaitai/python/record.h (renamed from plugins/yaml/python/tree.h)18
-rw-r--r--plugins/kaitai/python/records/Makefile.am19
-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.c341
-rw-r--r--plugins/kaitai/python/records/delayed.h45
-rw-r--r--plugins/kaitai/python/records/empty.c286
-rw-r--r--plugins/kaitai/python/records/empty.h45
-rw-r--r--plugins/kaitai/python/records/group.c305
-rw-r--r--plugins/kaitai/python/records/group.h45
-rw-r--r--plugins/kaitai/python/records/item.c394
-rw-r--r--plugins/kaitai/python/records/item.h (renamed from plugins/yaml/python/line.h)18
-rw-r--r--plugins/kaitai/python/records/list.c (renamed from plugins/yaml/python/scalar.c)248
-rw-r--r--plugins/kaitai/python/records/list.h45
-rw-r--r--plugins/kaitai/python/records/module.c124
-rw-r--r--plugins/kaitai/python/records/module.h41
-rw-r--r--plugins/kaitai/python/rost/Makefile.am14
-rw-r--r--plugins/kaitai/python/rost/module.c115
-rw-r--r--plugins/kaitai/python/rost/module.h41
-rw-r--r--plugins/kaitai/python/rost/trigger.c236
-rw-r--r--plugins/kaitai/python/rost/trigger.h45
-rw-r--r--plugins/kaitai/python/scope.c542
-rw-r--r--plugins/kaitai/python/scope.h51
-rw-r--r--plugins/kaitai/python/stream.c278
-rw-r--r--plugins/kaitai/python/stream.h45
-rw-r--r--plugins/kaitai/record-int.h73
-rw-r--r--plugins/kaitai/record.c416
-rw-r--r--plugins/kaitai/record.h88
-rw-r--r--plugins/kaitai/records/Makefile.am23
-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.h60
-rw-r--r--plugins/kaitai/records/delayed.c352
-rw-r--r--plugins/kaitai/records/delayed.h65
-rw-r--r--plugins/kaitai/records/empty-int.h57
-rw-r--r--plugins/kaitai/records/empty.c236
-rw-r--r--plugins/kaitai/records/empty.h58
-rw-r--r--plugins/kaitai/records/group-int.h58
-rw-r--r--plugins/kaitai/records/group.c382
-rw-r--r--plugins/kaitai/records/group.h65
-rw-r--r--plugins/kaitai/records/item-int.h58
-rw-r--r--plugins/kaitai/records/item.c (renamed from plugins/yaml/scalar.c)293
-rw-r--r--plugins/kaitai/records/item.h65
-rw-r--r--plugins/kaitai/records/list-int.h60
-rw-r--r--plugins/kaitai/records/list.c424
-rw-r--r--plugins/kaitai/records/list.h71
-rw-r--r--plugins/kaitai/rost/Makefile.am18
-rw-r--r--plugins/kaitai/rost/browser-int.h58
-rw-r--r--plugins/kaitai/rost/browser.c478
-rw-r--r--plugins/kaitai/rost/browser.h58
-rw-r--r--plugins/kaitai/rost/core.c66
-rw-r--r--plugins/kaitai/rost/core.h37
-rw-r--r--plugins/kaitai/rost/space-int.h55
-rw-r--r--plugins/kaitai/rost/space.c254
-rw-r--r--plugins/kaitai/rost/space.h59
-rw-r--r--plugins/kaitai/rost/trigger-int.h59
-rw-r--r--plugins/kaitai/rost/trigger.c320
-rw-r--r--plugins/kaitai/rost/trigger.h61
-rw-r--r--plugins/kaitai/scope.c257
-rw-r--r--plugins/kaitai/scope.h72
-rw-r--r--plugins/kaitai/stream-int.h55
-rw-r--r--plugins/kaitai/stream.c237
-rw-r--r--plugins/kaitai/stream.h65
-rw-r--r--plugins/kaitai/tokens.l329
-rw-r--r--plugins/libcsem/Makefile.am11
-rw-r--r--plugins/lnxsyscalls/Makefile.am25
-rw-r--r--plugins/lnxsyscalls/hunter.h2
-rw-r--r--plugins/mobicore/Makefile.am17
-rw-r--r--plugins/pe/Makefile.am24
-rw-r--r--plugins/pe/core.c7
-rw-r--r--plugins/pe/python/Makefile.am20
-rw-r--r--plugins/pe/python/format.c7
-rw-r--r--plugins/pe/python/routine.c8
-rw-r--r--plugins/pe/symbols.h2
-rw-r--r--plugins/pychrysalide/Makefile.am69
-rw-r--r--plugins/pychrysalide/analysis/Makefile.am35
-rw-r--r--plugins/pychrysalide/analysis/binary.c15
-rw-r--r--plugins/pychrysalide/analysis/block.c4
-rw-r--r--plugins/pychrysalide/analysis/cattribs.c81
-rw-r--r--plugins/pychrysalide/analysis/content.c133
-rw-r--r--plugins/pychrysalide/analysis/contents/Makefile.am19
-rw-r--r--plugins/pychrysalide/analysis/contents/encapsulated.c51
-rw-r--r--plugins/pychrysalide/analysis/contents/file.c52
-rw-r--r--plugins/pychrysalide/analysis/contents/memory.c56
-rw-r--r--plugins/pychrysalide/analysis/contents/restricted.c54
-rw-r--r--plugins/pychrysalide/analysis/db/Makefile.am28
-rw-r--r--plugins/pychrysalide/analysis/db/admin.c10
-rw-r--r--plugins/pychrysalide/analysis/db/analyst.c124
-rw-r--r--plugins/pychrysalide/analysis/db/client.c2
-rw-r--r--plugins/pychrysalide/analysis/db/collection.c2
-rw-r--r--plugins/pychrysalide/analysis/db/constants.c43
-rw-r--r--plugins/pychrysalide/analysis/db/constants.h3
-rw-r--r--plugins/pychrysalide/analysis/db/item.c2
-rw-r--r--plugins/pychrysalide/analysis/db/items/Makefile.am19
-rw-r--r--plugins/pychrysalide/analysis/db/items/bookmark.c8
-rw-r--r--plugins/pychrysalide/analysis/db/items/comment.c8
-rw-r--r--plugins/pychrysalide/analysis/db/items/switcher.c8
-rw-r--r--plugins/pychrysalide/analysis/db/server.c2
-rw-r--r--plugins/pychrysalide/analysis/disass/Makefile.am15
-rw-r--r--plugins/pychrysalide/analysis/disass/block.c5
-rw-r--r--plugins/pychrysalide/analysis/loaded.c266
-rw-r--r--plugins/pychrysalide/analysis/loading.c4
-rw-r--r--plugins/pychrysalide/analysis/module.c3
-rw-r--r--plugins/pychrysalide/analysis/project.c2
-rw-r--r--plugins/pychrysalide/analysis/routine.c2
-rw-r--r--plugins/pychrysalide/analysis/scan/Makefile.am28
-rw-r--r--plugins/pychrysalide/analysis/scan/constants.c128
-rw-r--r--plugins/pychrysalide/analysis/scan/constants.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/context.c432
-rw-r--r--plugins/pychrysalide/analysis/scan/context.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/core.c179
-rw-r--r--plugins/pychrysalide/analysis/scan/core.h39
-rw-r--r--plugins/pychrysalide/analysis/scan/expr.c393
-rw-r--r--plugins/pychrysalide/analysis/scan/expr.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/Makefile.am15
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/constants.c128
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/constants.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/literal.c281
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/literal.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/module.c103
-rw-r--r--plugins/pychrysalide/analysis/scan/exprs/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/item.c740
-rw-r--r--plugins/pychrysalide/analysis/scan/item.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/module.c125
-rw-r--r--plugins/pychrysalide/analysis/scan/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/options.c511
-rw-r--r--plugins/pychrysalide/analysis/scan/options.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/Makefile.am22
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backend.c202
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backend.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am15
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/acism.c214
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/acism.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c214
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/module.c106
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifier.c416
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifier.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am18
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c211
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c320
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c112
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c211
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c211
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c210
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/module.c114
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.c487
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/space.c283
-rw-r--r--plugins/pychrysalide/analysis/scan/space.h45
-rw-r--r--plugins/pychrysalide/analysis/storage/Makefile.am13
-rw-r--r--plugins/pychrysalide/analysis/storage/cache.c4
-rw-r--r--plugins/pychrysalide/analysis/storage/storage.c119
-rw-r--r--plugins/pychrysalide/analysis/storage/tpmem.c56
-rw-r--r--plugins/pychrysalide/analysis/type.c34
-rw-r--r--plugins/pychrysalide/analysis/types/Makefile.am33
-rw-r--r--plugins/pychrysalide/analysis/types/array.c2
-rw-r--r--plugins/pychrysalide/analysis/types/basic.c2
-rw-r--r--plugins/pychrysalide/analysis/types/cse.c2
-rw-r--r--plugins/pychrysalide/analysis/types/encaps.c2
-rw-r--r--plugins/pychrysalide/analysis/types/expr.c2
-rw-r--r--plugins/pychrysalide/analysis/types/literal.c2
-rw-r--r--plugins/pychrysalide/analysis/types/override.c2
-rw-r--r--plugins/pychrysalide/analysis/types/proto.c2
-rw-r--r--plugins/pychrysalide/analysis/types/template.c2
-rw-r--r--plugins/pychrysalide/analysis/variable.c2
-rw-r--r--plugins/pychrysalide/arch/Makefile.am28
-rw-r--r--plugins/pychrysalide/arch/context.c10
-rw-r--r--plugins/pychrysalide/arch/instruction.c282
-rw-r--r--plugins/pychrysalide/arch/instructions/Makefile.am19
-rw-r--r--plugins/pychrysalide/arch/instructions/raw.c4
-rw-r--r--plugins/pychrysalide/arch/instructions/undefined.c6
-rw-r--r--plugins/pychrysalide/arch/operand.c33
-rw-r--r--plugins/pychrysalide/arch/operands/Makefile.am32
-rw-r--r--plugins/pychrysalide/arch/operands/immediate.c370
-rw-r--r--plugins/pychrysalide/arch/operands/immediate.h17
-rw-r--r--plugins/pychrysalide/arch/operands/known.c224
-rw-r--r--plugins/pychrysalide/arch/operands/known.h45
-rw-r--r--plugins/pychrysalide/arch/operands/module.c1
-rw-r--r--plugins/pychrysalide/arch/operands/proxy.c7
-rw-r--r--plugins/pychrysalide/arch/operands/register.c48
-rw-r--r--plugins/pychrysalide/arch/operands/target.c15
-rw-r--r--plugins/pychrysalide/arch/processor.c4
-rw-r--r--plugins/pychrysalide/arch/register.c8
-rw-r--r--plugins/pychrysalide/common/Makefile.am26
-rw-r--r--plugins/pychrysalide/common/bits.c301
-rw-r--r--plugins/pychrysalide/common/bits.h3
-rw-r--r--plugins/pychrysalide/common/itoa.c124
-rw-r--r--plugins/pychrysalide/common/itoa.h39
-rw-r--r--plugins/pychrysalide/common/module.c2
-rw-r--r--plugins/pychrysalide/core.c242
-rw-r--r--plugins/pychrysalide/core.h3
-rw-r--r--plugins/pychrysalide/core/Makefile.am25
-rw-r--r--plugins/pychrysalide/core/global.c47
-rw-r--r--plugins/pychrysalide/core/queue.c17
-rw-r--r--plugins/pychrysalide/debug/Makefile.am17
-rw-r--r--plugins/pychrysalide/debug/debugger.c2
-rw-r--r--plugins/pychrysalide/format/Makefile.am32
-rw-r--r--plugins/pychrysalide/format/executable.c2
-rw-r--r--plugins/pychrysalide/format/flat.c2
-rw-r--r--plugins/pychrysalide/format/format.c4
-rw-r--r--plugins/pychrysalide/format/known.c4
-rw-r--r--plugins/pychrysalide/format/module.c2
-rw-r--r--plugins/pychrysalide/format/preload.c207
-rw-r--r--plugins/pychrysalide/format/preload.h45
-rw-r--r--plugins/pychrysalide/format/strsym.c4
-rw-r--r--plugins/pychrysalide/format/symbol.c13
-rw-r--r--plugins/pychrysalide/glibext/Makefile.am40
-rw-r--r--plugins/pychrysalide/glibext/binarycursor.c2
-rw-r--r--plugins/pychrysalide/glibext/binportion.c4
-rw-r--r--plugins/pychrysalide/glibext/buffercache.c16
-rw-r--r--plugins/pychrysalide/glibext/bufferline.c4
-rw-r--r--plugins/pychrysalide/glibext/bufferview.c2
-rw-r--r--plugins/pychrysalide/glibext/comparison.c341
-rw-r--r--plugins/pychrysalide/glibext/comparison.h45
-rw-r--r--plugins/pychrysalide/glibext/configuration.c8
-rw-r--r--plugins/pychrysalide/glibext/constants.c53
-rw-r--r--plugins/pychrysalide/glibext/constants.h7
-rw-r--r--plugins/pychrysalide/glibext/linecursor.c2
-rw-r--r--plugins/pychrysalide/glibext/module.c6
-rw-r--r--plugins/pychrysalide/glibext/singleton.c8
-rw-r--r--plugins/pychrysalide/gtkext/Makefile.am25
-rw-r--r--plugins/pychrysalide/gtkext/blockdisplay.c2
-rw-r--r--plugins/pychrysalide/gtkext/bufferdisplay.c2
-rw-r--r--plugins/pychrysalide/gtkext/displaypanel.c25
-rw-r--r--plugins/pychrysalide/gtkext/graph/Makefile.am17
-rw-r--r--plugins/pychrysalide/gtkext/graph/cluster.c2
-rw-r--r--plugins/pychrysalide/gtkext/graph/edge.c2
-rw-r--r--plugins/pychrysalide/gtkext/named.c11
-rw-r--r--plugins/pychrysalide/gui/Makefile.am22
-rw-r--r--plugins/pychrysalide/gui/core/Makefile.am17
-rw-r--r--plugins/pychrysalide/gui/item.c62
-rw-r--r--plugins/pychrysalide/gui/menubar.c5
-rw-r--r--plugins/pychrysalide/gui/panel.c5
-rw-r--r--plugins/pychrysalide/gui/panels/Makefile.am13
-rw-r--r--plugins/pychrysalide/helpers.c428
-rw-r--r--plugins/pychrysalide/helpers.h181
-rw-r--r--plugins/pychrysalide/mangling/Makefile.am17
-rw-r--r--plugins/pychrysalide/mangling/demangler.c56
-rw-r--r--plugins/pychrysalide/mangling/demangler.h2
-rw-r--r--plugins/pychrysalide/plugins/Makefile.am21
-rw-r--r--plugins/pychrysalide/plugins/plugin.c606
-rw-r--r--plugins/pychrysalide/plugins/plugin.h32
-rw-r--r--plugins/pychrysalide/weak.h6
-rw-r--r--plugins/python/cglimpse/panel.py6
-rw-r--r--plugins/python/scripting/core.py3
-rw-r--r--plugins/readdex/Makefile.am17
-rw-r--r--plugins/readdex/class.h2
-rw-r--r--plugins/readdex/ids.h2
-rw-r--r--plugins/readelf/Makefile.am18
-rw-r--r--plugins/readmc/Makefile.am19
-rw-r--r--plugins/ropgadgets/Makefile.am7
-rw-r--r--plugins/ropgadgets/plugin.c3
-rw-r--r--plugins/ropgadgets/select.c2
-rw-r--r--plugins/winordinals/Makefile.am6
-rw-r--r--plugins/winordinals/assign.h2
-rw-r--r--plugins/winordinals/core.c6
-rw-r--r--plugins/winordinals/python/Makefile.am9
-rw-r--r--plugins/yaml/Makefile.am15
-rw-r--r--plugins/yaml/collection-int.h60
-rw-r--r--plugins/yaml/collection.c164
-rw-r--r--plugins/yaml/collection.h19
-rw-r--r--plugins/yaml/core.c8
-rw-r--r--plugins/yaml/core.h2
-rw-r--r--plugins/yaml/line.h75
-rw-r--r--plugins/yaml/node-int.h20
-rw-r--r--plugins/yaml/node.c130
-rw-r--r--plugins/yaml/node.h23
-rw-r--r--plugins/yaml/pair-int.h66
-rw-r--r--plugins/yaml/pair.c427
-rw-r--r--plugins/yaml/pair.h28
-rw-r--r--plugins/yaml/parser.c299
-rw-r--r--plugins/yaml/parser.h43
-rw-r--r--plugins/yaml/python/Makefile.am15
-rw-r--r--plugins/yaml/python/collection.c81
-rw-r--r--plugins/yaml/python/collection.h6
-rw-r--r--plugins/yaml/python/constants.c127
-rw-r--r--plugins/yaml/python/constants.h42
-rw-r--r--plugins/yaml/python/module.c29
-rw-r--r--plugins/yaml/python/node.c199
-rw-r--r--plugins/yaml/python/node.h6
-rw-r--r--plugins/yaml/python/pair.c314
-rw-r--r--plugins/yaml/python/pair.h6
-rw-r--r--plugins/yaml/python/parser.c186
-rw-r--r--plugins/yaml/python/parser.h39
-rw-r--r--plugins/yaml/python/reader.c388
-rw-r--r--plugins/yaml/python/tree.c427
-rw-r--r--plugins/yaml/reader.h69
-rw-r--r--plugins/yaml/scalar.h72
-rw-r--r--plugins/yaml/tree.c421
-rw-r--r--plugins/yaml/tree.h69
543 files changed, 48062 insertions, 7886 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 8d39c37..1cda6e0 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -5,6 +5,12 @@ PYTHON3_SUBDIRS = pychrysalide python
endif
+if BUILD_GTK_SUPPORT
+
+ROPGADGETS_SUBDIRS = ropgadgets
+
+endif
+
# androhelpers
SUBDIRS = \
$(PYTHON3_SUBDIRS) \
@@ -18,15 +24,18 @@ SUBDIRS = \
fmtp \
itanium \
javadesc \
+ kaitai \
mobicore \
pe \
yaml \
+ apihashing \
bhash \
dalvik \
+ encodings \
libcsem \
lnxsyscalls \
readdex \
readelf \
readmc \
- ropgadgets \
+ $(ROPGADGETS_SUBDIRS) \
winordinals
diff --git a/plugins/apihashing/Makefile.am b/plugins/apihashing/Makefile.am
new file mode 100644
index 0000000..d73f8b0
--- /dev/null
+++ b/plugins/apihashing/Makefile.am
@@ -0,0 +1,65 @@
+
+lib_LTLIBRARIES = libapihashing.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON_PACKAGE
+
+RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs:$$ORIGIN'
+
+else
+
+RUN_PATH = -Wl,-rpath,'$$ORIGIN'
+
+endif
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD = python/libapihashingpython.la
+
+if BUILD_DISCARD_LOCAL
+
+if BUILD_PYTHON_PACKAGE
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN/..'
+else
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN'
+endif
+
+else
+
+PYTHON3_RUN_PATH = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs
+
+endif
+
+PYTHON3_LDFLAGS = $(PYTHON3_RUN_PATH) -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libapihashing_la_SOURCES = \
+ apihash.h apihash.c \
+ core.h core.c
+
+libapihashing_la_LIBADD = \
+ $(PYTHON3_LIBADD) \
+ classics/libapihashingclassics.la \
+ custom/libapihashingcustom.la
+
+libapihashing_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+libapihashing_la_LDFLAGS = \
+ -avoid-version \
+ -L$(top_srcdir)/src/.libs -lchrysacore \
+ -L$(top_srcdir)/plugins/pe/.libs -lpe \
+ $(RUN_PATH) $(PYTHON3_LDFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libapihashing_la_SOURCES:%c=)
+
+
+SUBDIRS = $(PYTHON3_SUBDIRS) classics custom
diff --git a/plugins/apihashing/apihash.c b/plugins/apihashing/apihash.c
new file mode 100644
index 0000000..3313073
--- /dev/null
+++ b/plugins/apihashing/apihash.c
@@ -0,0 +1,134 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * apihash.c - détermination d'API par empreinte de fonction
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "apihash.h"
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en empreintes d'API. */
+static void g_api_hash_modifier_class_init(GApiHashModifierClass *klass);
+
+/* Initialise une instance de transmission en empreinte d'API. */
+static void g_api_hash_modifier_init(GApiHashModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_api_hash_modifier_dispose(GApiHashModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_api_hash_modifier_finalize(GApiHashModifier *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte d'API. */
+G_DEFINE_TYPE(GApiHashModifier, g_api_hash_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en empreintes d'API. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_api_hash_modifier_class_init(GApiHashModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_api_hash_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_api_hash_modifier_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en empreinte d'API. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_api_hash_modifier_init(GApiHashModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_api_hash_modifier_dispose(GApiHashModifier *modifier)
+{
+ G_OBJECT_CLASS(g_api_hash_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_api_hash_modifier_finalize(GApiHashModifier *modifier)
+{
+ G_OBJECT_CLASS(g_api_hash_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
diff --git a/plugins/apihashing/apihash.h b/plugins/apihashing/apihash.h
new file mode 100644
index 0000000..cfc3365
--- /dev/null
+++ b/plugins/apihashing/apihash.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * apihash.h - prototypes pour la détermination d'API par empreinte de fonction
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_APIHASH_H
+#define _PLUGINS_APIHASHING_APIHASH_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/scan/patterns/modifier.h>
+
+
+
+#define G_TYPE_API_HASH_MODIFIER g_api_hash_modifier_get_type()
+#define G_API_HASH_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_API_HASH_MODIFIER, GApiHashModifier))
+#define G_IS_API_HASH_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_API_HASH_MODIFIER))
+#define G_API_HASH_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_API_HASH_MODIFIER, GApiHashModifierClass))
+#define G_IS_API_HASH_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_API_HASH_MODIFIER))
+#define G_API_HASH_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_API_HASH_MODIFIER, GApiHashModifierClass))
+
+
+/* Transormation en empreinte d'API (instance) */
+typedef GScanTokenModifier GApiHashModifier;
+
+/* Transormation en empreinte d'API (classe) */
+typedef GScanTokenModifierClass GApiHashModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte d'API. */
+GType g_api_hash_modifier_get_type(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_APIHASH_H */
diff --git a/plugins/apihashing/classics/Makefile.am b/plugins/apihashing/classics/Makefile.am
new file mode 100644
index 0000000..9f97b47
--- /dev/null
+++ b/plugins/apihashing/classics/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_LTLIBRARIES = libapihashingclassics.la
+
+libapihashingclassics_la_SOURCES = \
+ crc32.h crc32.c \
+ djb2.h djb2.c \
+ ror13.h ror13.c
+
+libapihashingclassics_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libapihashingclassics_la_SOURCES:%c=)
diff --git a/plugins/apihashing/classics/crc32.c b/plugins/apihashing/classics/crc32.c
new file mode 100644
index 0000000..98f9a6b
--- /dev/null
+++ b/plugins/apihashing/classics/crc32.c
@@ -0,0 +1,332 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * crc32.c - transormation en empreinte d'API crc32
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "crc32.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en empreintes crc32. */
+static void g_scan_crc32_modifier_class_init(GScanCrc32ModifierClass *klass);
+
+/* Initialise une instance de transmission en empreinte crc32. */
+static void g_scan_crc32_modifier_init(GScanCrc32Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_crc32_modifier_dispose(GScanCrc32Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_crc32_modifier_finalize(GScanCrc32Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_crc32_modifier_get_name(const GScanCrc32Modifier *);
+
+/* Calcule l'empreinte crc32 d'un motif de recherche. */
+static uint32_t compute_crc32(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_crc32_modifier_transform(const GScanCrc32Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_crc32_modifier_get_path(const GScanCrc32Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en encodage Crc32. */
+G_DEFINE_TYPE(GScanCrc32Modifier, g_scan_crc32_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en empreintes crc32. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_crc32_modifier_class_init(GScanCrc32ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_crc32_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_crc32_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_crc32_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_crc32_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_crc32_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en empreinte crc32. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_crc32_modifier_init(GScanCrc32Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_crc32_modifier_dispose(GScanCrc32Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_crc32_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_crc32_modifier_finalize(GScanCrc32Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_crc32_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des empreintes crc32. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_crc32_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_CRC32_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_crc32_modifier_get_name(const GScanCrc32Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("crc32");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte crc32 d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_crc32(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ size_t k; /* Boucle de parcours #2 */
+
+ result = 0xffffffff;
+
+ for (i = 0; i < src->len; i++)
+ {
+ result ^= src->data[i];
+
+ for (k = 0; k < 8; k++)
+ result = result & 1 ? (result >> 1) ^ 0xedb88320 : result >> 1;
+
+ }
+
+ result = ~result;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_crc32_modifier_transform(const GScanCrc32Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_crc32(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_crc32_modifier_get_path(const GScanCrc32Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("crc32");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/classics/crc32.h b/plugins/apihashing/classics/crc32.h
new file mode 100644
index 0000000..0198c5d
--- /dev/null
+++ b/plugins/apihashing/classics/crc32.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * crc32.h - prototypes pour la transormation en empreinte d'API crc32
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CLASSICS_CRC32_H
+#define _PLUGINS_APIHASHING_CLASSICS_CRC32_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_CRC32_MODIFIER g_scan_crc32_modifier_get_type()
+#define G_SCAN_CRC32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_CRC32_MODIFIER, GScanCrc32Modifier))
+#define G_IS_SCAN_CRC32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_CRC32_MODIFIER))
+#define G_SCAN_CRC32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_CRC32_MODIFIER, GScanCrc32ModifierClass))
+#define G_IS_SCAN_CRC32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_CRC32_MODIFIER))
+#define G_SCAN_CRC32_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_CRC32_MODIFIER, GScanCrc32ModifierClass))
+
+
+/* Transormation en empreinte d'API crc32 (instance) */
+typedef GApiHashModifier GScanCrc32Modifier;
+
+/* Transormation en empreinte d'API crc32 (classe) */
+typedef GApiHashModifierClass GScanCrc32ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte crc32. */
+GType g_scan_crc32_modifier_get_type(void);
+
+/* Construit un modificateur livrant des empreintes crc32. */
+GScanTokenModifier *g_scan_crc32_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CLASSICS_CRC32_H */
diff --git a/plugins/apihashing/classics/djb2.c b/plugins/apihashing/classics/djb2.c
new file mode 100644
index 0000000..524218f
--- /dev/null
+++ b/plugins/apihashing/classics/djb2.c
@@ -0,0 +1,323 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * djb2.c - transormation en empreinte d'API djb2
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "djb2.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en empreintes djb2. */
+static void g_scan_djb2_modifier_class_init(GScanDjb2ModifierClass *klass);
+
+/* Initialise une instance de transmission en empreinte djb2. */
+static void g_scan_djb2_modifier_init(GScanDjb2Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_djb2_modifier_dispose(GScanDjb2Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_djb2_modifier_finalize(GScanDjb2Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_djb2_modifier_get_name(const GScanDjb2Modifier *);
+
+/* Calcule l'empreinte djb2 d'un motif de recherche. */
+static uint32_t compute_djb2(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_djb2_modifier_transform(const GScanDjb2Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_djb2_modifier_get_path(const GScanDjb2Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en encodage Djb2. */
+G_DEFINE_TYPE(GScanDjb2Modifier, g_scan_djb2_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en empreintes djb2. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_djb2_modifier_class_init(GScanDjb2ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_djb2_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_djb2_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_djb2_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_djb2_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_djb2_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en empreinte djb2. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_djb2_modifier_init(GScanDjb2Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_djb2_modifier_dispose(GScanDjb2Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_djb2_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_djb2_modifier_finalize(GScanDjb2Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_djb2_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des empreintes djb2. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_djb2_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_DJB2_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_djb2_modifier_get_name(const GScanDjb2Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("djb2");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte djb2 d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_djb2(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = 0x1505; /* 5381 */
+
+ for (i = 0; i < src->len; i++)
+ result = ((result << 5) + result) + src->data[i]; /* hash * 33 + c */
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_djb2_modifier_transform(const GScanDjb2Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_djb2(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_djb2_modifier_get_path(const GScanDjb2Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("djb2");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/classics/djb2.h b/plugins/apihashing/classics/djb2.h
new file mode 100644
index 0000000..04df1df
--- /dev/null
+++ b/plugins/apihashing/classics/djb2.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * djb2.h - prototypes pour la transormation en empreinte d'API djb2
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CLASSICS_DJB2_H
+#define _PLUGINS_APIHASHING_CLASSICS_DJB2_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_DJB2_MODIFIER g_scan_djb2_modifier_get_type()
+#define G_SCAN_DJB2_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_DJB2_MODIFIER, GScanDjb2Modifier))
+#define G_IS_SCAN_DJB2_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_DJB2_MODIFIER))
+#define G_SCAN_DJB2_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_DJB2_MODIFIER, GScanDjb2ModifierClass))
+#define G_IS_SCAN_DJB2_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_DJB2_MODIFIER))
+#define G_SCAN_DJB2_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_DJB2_MODIFIER, GScanDjb2ModifierClass))
+
+
+/* Transormation en empreinte d'API DJB2 (instance) */
+typedef GApiHashModifier GScanDjb2Modifier;
+
+/* Transormation en empreinte d'API DJB2 (classe) */
+typedef GApiHashModifierClass GScanDjb2ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte djb2. */
+GType g_scan_djb2_modifier_get_type(void);
+
+/* Construit un modificateur livrant des empreintes djb2. */
+GScanTokenModifier *g_scan_djb2_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CLASSICS_DJB2_H */
diff --git a/plugins/apihashing/classics/ror13.c b/plugins/apihashing/classics/ror13.c
new file mode 100644
index 0000000..e557804
--- /dev/null
+++ b/plugins/apihashing/classics/ror13.c
@@ -0,0 +1,323 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ror13.c - transormation en empreinte d'API ror13
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "ror13.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en empreintes ror13. */
+static void g_scan_ror13_modifier_class_init(GScanRor13ModifierClass *klass);
+
+/* Initialise une instance de transmission en empreinte ror13. */
+static void g_scan_ror13_modifier_init(GScanRor13Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_ror13_modifier_dispose(GScanRor13Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_ror13_modifier_finalize(GScanRor13Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_ror13_modifier_get_name(const GScanRor13Modifier *);
+
+/* Calcule l'empreinte ror13 d'un motif de recherche. */
+static uint32_t compute_ror13(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_ror13_modifier_transform(const GScanRor13Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_ror13_modifier_get_path(const GScanRor13Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte ror13. */
+G_DEFINE_TYPE(GScanRor13Modifier, g_scan_ror13_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en empreintes ror13. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_ror13_modifier_class_init(GScanRor13ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_ror13_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_ror13_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_ror13_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_ror13_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_ror13_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en empreinte ror13. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_ror13_modifier_init(GScanRor13Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_ror13_modifier_dispose(GScanRor13Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_ror13_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_ror13_modifier_finalize(GScanRor13Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_ror13_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des empreintes ror13. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_ror13_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_ROR13_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_ror13_modifier_get_name(const GScanRor13Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("ror13");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte ror13 d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_ror13(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = 0;
+
+ for (i = 0; i < src->len; i++)
+ result = src->data[i] + ((result << 19) | (result >> 13));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_ror13_modifier_transform(const GScanRor13Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_ror13(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_ror13_modifier_get_path(const GScanRor13Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("ror13");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/classics/ror13.h b/plugins/apihashing/classics/ror13.h
new file mode 100644
index 0000000..43480bd
--- /dev/null
+++ b/plugins/apihashing/classics/ror13.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ror13.h - prototypes pour la transormation en empreinte d'API ror13
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CLASSICS_ROR13_H
+#define _PLUGINS_APIHASHING_CLASSICS_ROR13_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_ROR13_MODIFIER g_scan_ror13_modifier_get_type()
+#define G_SCAN_ROR13_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ROR13_MODIFIER, GScanRor13Modifier))
+#define G_IS_SCAN_ROR13_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ROR13_MODIFIER))
+#define G_SCAN_ROR13_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ROR13_MODIFIER, GScanRor13ModifierClass))
+#define G_IS_SCAN_ROR13_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ROR13_MODIFIER))
+#define G_SCAN_ROR13_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ROR13_MODIFIER, GScanRor13ModifierClass))
+
+
+/* Transormation en empreinte d'API ror13 (instance) */
+typedef GApiHashModifier GScanRor13Modifier;
+
+/* Transormation en empreinte d'API ror13 (classe) */
+typedef GApiHashModifierClass GScanRor13ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte ror13. */
+GType g_scan_ror13_modifier_get_type(void);
+
+/* Construit un modificateur livrant des empreintes ror13. */
+GScanTokenModifier *g_scan_ror13_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CLASSICS_ROR13_H */
diff --git a/plugins/apihashing/core.c b/plugins/apihashing/core.c
new file mode 100644
index 0000000..a74a637
--- /dev/null
+++ b/plugins/apihashing/core.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - prototypes pour le calcul d'encodages
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <analysis/scan/core.h>
+#include <plugins/self.h>
+
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+# include "python/module.h"
+# include "python/classics/module.h"
+#endif
+#include "classics/crc32.h"
+#include "classics/djb2.h"
+#include "classics/ror13.h"
+#include "custom/add1505-shl5.h"
+#include "custom/enigma-murmur.h"
+#include "custom/imul21-add.h"
+#include "custom/imul83-add.h"
+#include "custom/sll1-add-hash32.h"
+#include "custom/sub-index1.h"
+#include "custom/sub42.h"
+
+
+#ifdef INCLUDE_PYTHON3_BINDINGS_
+# define PG_REQ RL("PyChrysalide")
+#else
+# define PG_REQ NO_REQ
+#endif
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("ApiHashing", "API hash computing as ROST modifiers",
+ PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"),
+ PG_REQ, AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Prend acte du chargement du greffon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+#define REGISTER_SCAN_MODIFIER(m) \
+ ({ \
+ GScanTokenModifier *__mod; \
+ bool __status; \
+ __mod = m; \
+ __status = register_scan_token_modifier(__mod); \
+ g_object_unref(G_OBJECT(__mod)); \
+ __status; \
+ })
+
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_crc32_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_djb2_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_ror13_modifier_new());
+
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_add1505_shl5_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_enigma_murmur_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_imul21_add_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_imul83_add_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_sll1_add_hash32_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_sub42_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_sub_index1_modifier_new());
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+
+ if (result) result = add_apihashing_module_to_python_module();
+ if (result) result = register_apihashing_classics_modifiers();
+
+#endif
+
+ return result;
+
+}
diff --git a/plugins/apihashing/core.h b/plugins/apihashing/core.h
new file mode 100644
index 0000000..75a6e73
--- /dev/null
+++ b/plugins/apihashing/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour le calcul d'encodages
+ *
+ * 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_ENCODINGS_CORE_H
+#define _PLUGINS_ENCODINGS_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_CORE_H */
diff --git a/plugins/apihashing/custom/Makefile.am b/plugins/apihashing/custom/Makefile.am
new file mode 100644
index 0000000..026addc
--- /dev/null
+++ b/plugins/apihashing/custom/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libapihashingcustom.la
+
+libapihashingcustom_la_SOURCES = \
+ add1505-shl5.h add1505-shl5.c \
+ enigma-murmur.h enigma-murmur.c \
+ imul21-add.h imul21-add.c \
+ imul83-add.h imul83-add.c \
+ sll1-add-hash32.h sll1-add-hash32.c \
+ sub-index1.h sub-index1.c \
+ sub42.h sub42.c
+
+libapihashingcustom_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libapihashingcustom_la_SOURCES:%c=)
diff --git a/plugins/apihashing/custom/add1505-shl5.c b/plugins/apihashing/custom/add1505-shl5.c
new file mode 100644
index 0000000..db96cf1
--- /dev/null
+++ b/plugins/apihashing/custom/add1505-shl5.c
@@ -0,0 +1,325 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * add1505-shl5.c - transormation en empreinte d'API add1505-shl5
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "add1505-shl5.h"
+
+
+#include <malloc.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en empreintes add1505-shl5. */
+static void g_scan_add1505_shl5_modifier_class_init(GScanAdd1505Shl5ModifierClass *);
+
+/* Initialise une instance de transmission en empreinte add1505-shl5. */
+static void g_scan_add1505_shl5_modifier_init(GScanAdd1505Shl5Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_add1505_shl5_modifier_dispose(GScanAdd1505Shl5Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_add1505_shl5_modifier_finalize(GScanAdd1505Shl5Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_add1505_shl5_modifier_get_name(const GScanAdd1505Shl5Modifier *);
+
+/* Calcule l'empreinte add1505-shl5 d'un motif de recherche. */
+static uint32_t compute_add1505_shl5_hash32(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_add1505_shl5_modifier_transform(const GScanAdd1505Shl5Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_add1505_shl5_modifier_get_path(const GScanAdd1505Shl5Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte add1505-shl5. */
+G_DEFINE_TYPE(GScanAdd1505Shl5Modifier, g_scan_add1505_shl5_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en empreintes add1505-shl5. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_add1505_shl5_modifier_class_init(GScanAdd1505Shl5ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_add1505_shl5_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_add1505_shl5_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_add1505_shl5_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_add1505_shl5_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_add1505_shl5_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en empreinte add1505-shl5. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_add1505_shl5_modifier_init(GScanAdd1505Shl5Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_add1505_shl5_modifier_dispose(GScanAdd1505Shl5Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_add1505_shl5_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_add1505_shl5_modifier_finalize(GScanAdd1505Shl5Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_add1505_shl5_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des empreintes add1505-shl5. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_add1505_shl5_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_add1505_shl5_modifier_get_name(const GScanAdd1505Shl5Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("add1505-shl5");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte add1505-shl5 d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_add1505_shl5_hash32(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = 0x1505;
+
+ for (i = 0; i < src->len; i++)
+ {
+ result += (result << 5);
+ result += src->data[i];
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_add1505_shl5_modifier_transform(const GScanAdd1505Shl5Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_add1505_shl5_hash32(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_add1505_shl5_modifier_get_path(const GScanAdd1505Shl5Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("add1505-shl5");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/add1505-shl5.h b/plugins/apihashing/custom/add1505-shl5.h
new file mode 100644
index 0000000..5e71987
--- /dev/null
+++ b/plugins/apihashing/custom/add1505-shl5.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * add1505-shl5.h - prototypes pour la transormation en empreinte d'API add1505-shl5
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_ADD1505_SHL5_H
+#define _PLUGINS_APIHASHING_CUSTOM_ADD1505_SHL5_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_ADD1505_SHL5_MODIFIER g_scan_add1505_shl5_modifier_get_type()
+#define G_SCAN_ADD1505_SHL5_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, GScanAdd1505Shl5Modifier))
+#define G_IS_SCAN_ADD1505_SHL5_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER))
+#define G_SCAN_ADD1505_SHL5_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, GScanAdd1505Shl5ModifierClass))
+#define G_IS_SCAN_ADD1505_SHL5_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER))
+#define G_SCAN_ADD1505_SHL5_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, GScanAdd1505Shl5ModifierClass))
+
+
+/* Transormation en empreinte d'API add1505-shl5 (instance) */
+typedef GApiHashModifier GScanAdd1505Shl5Modifier;
+
+/* Transormation en empreinte d'API add1505-shl5 (classe) */
+typedef GApiHashModifierClass GScanAdd1505Shl5ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte add1505-shl5. */
+GType g_scan_add1505_shl5_modifier_get_type(void);
+
+/* Construit un modificateur livrant des empreintes add1505-shl5. */
+GScanTokenModifier *g_scan_add1505_shl5_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_ADD1505_SHL5_H */
diff --git a/plugins/apihashing/custom/enigma-murmur.c b/plugins/apihashing/custom/enigma-murmur.c
new file mode 100644
index 0000000..cdc35b0
--- /dev/null
+++ b/plugins/apihashing/custom/enigma-murmur.c
@@ -0,0 +1,377 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enigma-murmur.c - transormation en empreinte d'API enigma-murmur
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "enigma-murmur.h"
+
+
+#include <malloc.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des empreintes enigma-murmur. */
+static void g_scan_enigma_murmur_modifier_class_init(GScanEnigmaMurmurModifierClass *);
+
+/* Initialise une instance d'empreinte enigma-murmur. */
+static void g_scan_enigma_murmur_modifier_init(GScanEnigmaMurmurModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_enigma_murmur_modifier_dispose(GScanEnigmaMurmurModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_enigma_murmur_modifier_finalize(GScanEnigmaMurmurModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_enigma_murmur_modifier_get_name(const GScanEnigmaMurmurModifier *);
+
+/* Calcule l'empreinte enigma-murmur d'un motif de recherche. */
+static uint32_t compute_enigma_murmur_hash32(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_enigma_murmur_modifier_transform(const GScanEnigmaMurmurModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_enigma_murmur_modifier_get_path(const GScanEnigmaMurmurModifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte enigma-murmur. */
+G_DEFINE_TYPE(GScanEnigmaMurmurModifier, g_scan_enigma_murmur_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des empreintes enigma-murmur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_enigma_murmur_modifier_class_init(GScanEnigmaMurmurModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_enigma_murmur_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_enigma_murmur_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_enigma_murmur_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_enigma_murmur_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_enigma_murmur_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance d'empreinte enigma-murmur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_enigma_murmur_modifier_init(GScanEnigmaMurmurModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_enigma_murmur_modifier_dispose(GScanEnigmaMurmurModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_enigma_murmur_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_enigma_murmur_modifier_finalize(GScanEnigmaMurmurModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_enigma_murmur_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur pour des empreintes enigma-murmur. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_enigma_murmur_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_enigma_murmur_modifier_get_name(const GScanEnigmaMurmurModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("enigma-murmur");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte enigma-murmur d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_enigma_murmur_hash32(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t blk_count; /* Nombre de blocs présents */
+ size_t i; /* Boucle de parcours */
+ uint32_t k; /* Valeur pour un bloc */
+ const bin_t *tail; /* Fragement de bloc final */
+
+ result = 0x4a03bdfa;
+
+ /* Traitement par blocs de 4 octets */
+
+ blk_count = src->len / 4;
+
+ for (i = 0; i < blk_count; i++)
+ {
+ k = ((uint32_t *)src->data)[i];
+
+ k *= 0xcc9e2d51;
+ k = (k << 15) | (k >> 17);
+ k *= 0x1b873593;
+
+ result ^= k;
+ result = (result << 13) | (result >> 19);
+ result = result * 5 + 0xe6546b64;
+
+ }
+
+ /* Traitement du reste */
+
+ tail = src->static_bin_data + 4 * blk_count;
+
+ k = 0;
+
+ switch (src->len & 3)
+ {
+ case 3:
+ k ^= (tail[2] << 16);
+
+ case 2:
+ k ^= (tail[1] << 8);
+
+ case 1:
+ k ^= tail[0];
+ k *= 0xcc9e2d51;
+ k = (k << 15) | (k >> (17));
+ k *= 0x1b873593;
+ result ^= k;
+ break;
+
+ case 0:
+ break;
+
+ }
+
+ /* Conclusion */
+
+ result ^= src->len;
+
+ result ^= (result >> 16);
+ result *= 0x85ebca6b;
+ result ^= (result >> 13);
+ result *= 0xc2b2ae35;
+ result ^= (result >> 16);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_enigma_murmur_modifier_transform(const GScanEnigmaMurmurModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_enigma_murmur_hash32(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_enigma_murmur_modifier_get_path(const GScanEnigmaMurmurModifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("enigma-murmur");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/enigma-murmur.h b/plugins/apihashing/custom/enigma-murmur.h
new file mode 100644
index 0000000..29ae803
--- /dev/null
+++ b/plugins/apihashing/custom/enigma-murmur.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enigma-murmur.h - prototypes pour la transormation en empreinte d'API enigma-murmur
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_ENIGMA_MURMUR_H
+#define _PLUGINS_APIHASHING_CUSTOM_ENIGMA_MURMUR_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER g_scan_enigma_murmur_modifier_get_type()
+#define G_SCAN_ENIGMA_MURMUR_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, GScanEnigmaMurmurModifier))
+#define G_IS_SCAN_ENIGMA_MURMUR_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER))
+#define G_SCAN_ENIGMA_MURMUR_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, GScanEnigmaMurmurModifierClass))
+#define G_IS_SCAN_ENIGMA_MURMUR_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER))
+#define G_SCAN_ENIGMA_MURMUR_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, GScanEnigmaMurmurModifierClass))
+
+
+/* Transormation en empreinte d'API enigma-murmur (instance) */
+typedef GApiHashModifier GScanEnigmaMurmurModifier;
+
+/* Transormation en empreinte d'API enigma-murmur (classe) */
+typedef GApiHashModifierClass GScanEnigmaMurmurModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte enigma-murmur. */
+GType g_scan_enigma_murmur_modifier_get_type(void);
+
+/* Construit un modificateur pour des empreintes enigma-murmur. */
+GScanTokenModifier *g_scan_enigma_murmur_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_ENIGMA_MURMUR_H */
diff --git a/plugins/apihashing/custom/imul21-add.c b/plugins/apihashing/custom/imul21-add.c
new file mode 100644
index 0000000..2f71910
--- /dev/null
+++ b/plugins/apihashing/custom/imul21-add.c
@@ -0,0 +1,326 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul21-add.c - transormation en empreinte d'API imul21-add
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "imul21-add.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en imul21-add. */
+static void g_scan_imul21_add_modifier_class_init(GScanImul21AddModifierClass *);
+
+/* Initialise une instance de transmission en imul21-add. */
+static void g_scan_imul21_add_modifier_init(GScanImul21AddModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_imul21_add_modifier_dispose(GScanImul21AddModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_imul21_add_modifier_finalize(GScanImul21AddModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_imul21_add_modifier_get_name(const GScanImul21AddModifier *);
+
+/* Calcule l'empreinte imul21-add d'un motif de recherche. */
+static uint32_t compute_imul21_add(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_imul21_add_modifier_transform(const GScanImul21AddModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_imul21_add_modifier_get_path(const GScanImul21AddModifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte imul21-add. */
+G_DEFINE_TYPE(GScanImul21AddModifier, g_scan_imul21_add_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en imul21-add. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul21_add_modifier_class_init(GScanImul21AddModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_imul21_add_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_imul21_add_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_imul21_add_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_imul21_add_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_imul21_add_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en imul21-add. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul21_add_modifier_init(GScanImul21AddModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul21_add_modifier_dispose(GScanImul21AddModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_imul21_add_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul21_add_modifier_finalize(GScanImul21AddModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_imul21_add_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur vers empreintes imul21-add. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_imul21_add_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_IMUL21_ADD_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_imul21_add_modifier_get_name(const GScanImul21AddModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("imul21-add");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte imul21-add d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_imul21_add(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = 0;
+
+ for (i = 0; i < src->len; i++)
+ {
+ result *= 0x21;
+ result += src->data[i];
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_imul21_add_modifier_transform(const GScanImul21AddModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_imul21_add(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_imul21_add_modifier_get_path(const GScanImul21AddModifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("imul21-add");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/imul21-add.h b/plugins/apihashing/custom/imul21-add.h
new file mode 100644
index 0000000..fcaa140
--- /dev/null
+++ b/plugins/apihashing/custom/imul21-add.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul21-add.h - prototypes pour la transormation en empreinte d'API imul21-add
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_IMUL21_ADD_H
+#define _PLUGINS_APIHASHING_CUSTOM_IMUL21_ADD_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_IMUL21_ADD_MODIFIER g_scan_imul21_add_modifier_get_type()
+#define G_SCAN_IMUL21_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_IMUL21_ADD_MODIFIER, GScanImul21AddModifier))
+#define G_IS_SCAN_IMUL21_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_IMUL21_ADD_MODIFIER))
+#define G_SCAN_IMUL21_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_IMUL21_ADD_MODIFIER, GScanImul21AddModifierClass))
+#define G_IS_SCAN_IMUL21_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_IMUL21_ADD_MODIFIER))
+#define G_SCAN_IMUL21_ADD_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_IMUL21_ADD_MODIFIER, GScanImul21AddModifierClass))
+
+
+/* Transformation en empreinte d'API imul21-add (instance) */
+typedef GApiHashModifier GScanImul21AddModifier;
+
+/* Transformation en empreinte d'API imul21-add (classe) */
+typedef GApiHashModifierClass GScanImul21AddModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte imul21-add. */
+GType g_scan_imul21_add_modifier_get_type(void);
+
+/* Construit un modificateur vers empreintes imul21-add. */
+GScanTokenModifier *g_scan_imul21_add_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_IMUL21_ADD_H */
diff --git a/plugins/apihashing/custom/imul83-add.c b/plugins/apihashing/custom/imul83-add.c
new file mode 100644
index 0000000..29f8cf5
--- /dev/null
+++ b/plugins/apihashing/custom/imul83-add.c
@@ -0,0 +1,326 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul83-add.c - transormation en empreinte d'API imul83-add
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "imul83-add.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en imul83-add. */
+static void g_scan_imul83_add_modifier_class_init(GScanImul83AddModifierClass *);
+
+/* Initialise une instance de transmission en imul83-add. */
+static void g_scan_imul83_add_modifier_init(GScanImul83AddModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_imul83_add_modifier_dispose(GScanImul83AddModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_imul83_add_modifier_finalize(GScanImul83AddModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_imul83_add_modifier_get_name(const GScanImul83AddModifier *);
+
+/* Calcule l'empreinte imul83-add d'un motif de recherche. */
+static uint32_t compute_imul83_add(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_imul83_add_modifier_transform(const GScanImul83AddModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_imul83_add_modifier_get_path(const GScanImul83AddModifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte imul83-add. */
+G_DEFINE_TYPE(GScanImul83AddModifier, g_scan_imul83_add_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en imul83-add. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul83_add_modifier_class_init(GScanImul83AddModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_imul83_add_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_imul83_add_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_imul83_add_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_imul83_add_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_imul83_add_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en imul83-add. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul83_add_modifier_init(GScanImul83AddModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul83_add_modifier_dispose(GScanImul83AddModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_imul83_add_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_imul83_add_modifier_finalize(GScanImul83AddModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_imul83_add_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur vers empreintes imul83-add. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_imul83_add_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_IMUL83_ADD_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_imul83_add_modifier_get_name(const GScanImul83AddModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("imul83-add");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte imul83-add d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_imul83_add(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = 0;
+
+ for (i = 0; i < src->len; i++)
+ {
+ result *= 0x83;
+ result += src->data[i];
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_imul83_add_modifier_transform(const GScanImul83AddModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_imul83_add(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_imul83_add_modifier_get_path(const GScanImul83AddModifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("imul83-add");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/imul83-add.h b/plugins/apihashing/custom/imul83-add.h
new file mode 100644
index 0000000..7e376ee
--- /dev/null
+++ b/plugins/apihashing/custom/imul83-add.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul83-add.h - prototypes pour la transormation en empreinte d'API imul83-add
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_IMUL83_ADD_H
+#define _PLUGINS_APIHASHING_CUSTOM_IMUL83_ADD_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_IMUL83_ADD_MODIFIER g_scan_imul83_add_modifier_get_type()
+#define G_SCAN_IMUL83_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_IMUL83_ADD_MODIFIER, GScanImul83AddModifier))
+#define G_IS_SCAN_IMUL83_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_IMUL83_ADD_MODIFIER))
+#define G_SCAN_IMUL83_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_IMUL83_ADD_MODIFIER, GScanImul83AddModifierClass))
+#define G_IS_SCAN_IMUL83_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_IMUL83_ADD_MODIFIER))
+#define G_SCAN_IMUL83_ADD_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_IMUL83_ADD_MODIFIER, GScanImul83AddModifierClass))
+
+
+/* Transformation en empreinte d'API imul83-add (instance) */
+typedef GApiHashModifier GScanImul83AddModifier;
+
+/* Transformation en empreinte d'API imul83-add (classe) */
+typedef GApiHashModifierClass GScanImul83AddModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte imul83-add. */
+GType g_scan_imul83_add_modifier_get_type(void);
+
+/* Construit un modificateur vers empreintes imul83-add. */
+GScanTokenModifier *g_scan_imul83_add_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_IMUL83_ADD_H */
diff --git a/plugins/apihashing/custom/sll1-add-hash32.c b/plugins/apihashing/custom/sll1-add-hash32.c
new file mode 100644
index 0000000..de00f81
--- /dev/null
+++ b/plugins/apihashing/custom/sll1-add-hash32.c
@@ -0,0 +1,326 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sll1-add-hash32.c - transormation en empreinte d'API sll1-add-hash32
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "sll1-add-hash32.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en sll1-add-hash32. */
+static void g_scan_sll1_add_hash32_modifier_class_init(GScanSll1AddHash32ModifierClass *klass);
+
+/* Initialise une instance de transmission en sll1-add-hash32. */
+static void g_scan_sll1_add_hash32_modifier_init(GScanSll1AddHash32Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sll1_add_hash32_modifier_dispose(GScanSll1AddHash32Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sll1_add_hash32_modifier_finalize(GScanSll1AddHash32Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_sll1_add_hash32_modifier_get_name(const GScanSll1AddHash32Modifier *);
+
+/* Calcule l'empreinte sll1-add-hash32 d'un motif de recherche. */
+static uint32_t compute_sll1_add_hash32(const sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_sll1_add_hash32_modifier_transform(const GScanSll1AddHash32Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_sll1_add_hash32_modifier_get_path(const GScanSll1AddHash32Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte sll1-add-hash32. */
+G_DEFINE_TYPE(GScanSll1AddHash32Modifier, g_scan_sll1_add_hash32_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en sll1-add-hash32. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sll1_add_hash32_modifier_class_init(GScanSll1AddHash32ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sll1_add_hash32_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_sll1_add_hash32_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_sll1_add_hash32_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_sll1_add_hash32_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_sll1_add_hash32_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en sll1-add-hash32. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sll1_add_hash32_modifier_init(GScanSll1AddHash32Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sll1_add_hash32_modifier_dispose(GScanSll1AddHash32Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_sll1_add_hash32_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sll1_add_hash32_modifier_finalize(GScanSll1AddHash32Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_sll1_add_hash32_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur vers empreintes sll1-add-hash32. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_sll1_add_hash32_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_sll1_add_hash32_modifier_get_name(const GScanSll1AddHash32Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("sll1-add-hash32");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = séquence d'octets à traiter. *
+* *
+* Description : Calcule l'empreinte sll1-add-hash32 d'un motif de recherche. *
+* *
+* Retour : Valeur entière de l'empreinte déterminée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static uint32_t compute_sll1_add_hash32(const sized_binary_t *src)
+{
+ uint32_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = 0;
+
+ for (i = 0; i < src->len; i++)
+ {
+ result += (src->data[i] | 0x60);
+ result <<= 1;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_sll1_add_hash32_modifier_transform(const GScanSll1AddHash32Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ uint32_t hash; /* Valeur d'empreinte calculée */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ hash = compute_sll1_add_hash32(_src);
+
+ binary->data = malloc(sizeof(hash) * sizeof(bin_t));
+ binary->len = sizeof(hash);
+
+ memcpy(binary->data, &hash, sizeof(hash));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_sll1_add_hash32_modifier_get_path(const GScanSll1AddHash32Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("sll1-add-hash32");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/sll1-add-hash32.h b/plugins/apihashing/custom/sll1-add-hash32.h
new file mode 100644
index 0000000..39abee2
--- /dev/null
+++ b/plugins/apihashing/custom/sll1-add-hash32.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sll1-add-hash32.h - prototypes pour la transormation en empreinte d'API sll1-add-hash32
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_SLL1_ADD_HASH32_H
+#define _PLUGINS_APIHASHING_CUSTOM_SLL1_ADD_HASH32_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER g_scan_sll1_add_hash32_modifier_get_type()
+#define G_SCAN_SLL1_ADD_HASH32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, GScanSll1AddHash32Modifier))
+#define G_IS_SCAN_SLL1_ADD_HASH32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER))
+#define G_SCAN_SLL1_ADD_HASH32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, GScanSll1AddHash32ModifierClass))
+#define G_IS_SCAN_SLL1_ADD_HASH32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER))
+#define G_SCAN_SLL1_ADD_HASH32_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, GScanSll1AddHash32ModifierClass))
+
+
+/* Transormation en empreinte d'API sll1_add_hash32 (instance) */
+typedef GApiHashModifier GScanSll1AddHash32Modifier;
+
+/* Transormation en empreinte d'API sll1_add_hash32 (classe) */
+typedef GApiHashModifierClass GScanSll1AddHash32ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte sll1-add-hash32. */
+GType g_scan_sll1_add_hash32_modifier_get_type(void);
+
+/* Construit un modificateur vers empreintes sll1-add-hash32. */
+GScanTokenModifier *g_scan_sll1_add_hash32_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_SLL1_ADD_HASH32_H */
diff --git a/plugins/apihashing/custom/sub-index1.c b/plugins/apihashing/custom/sub-index1.c
new file mode 100644
index 0000000..79eafd8
--- /dev/null
+++ b/plugins/apihashing/custom/sub-index1.c
@@ -0,0 +1,291 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub-index1.c - transormation en empreinte d'API sub-index1
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "sub-index1.h"
+
+
+#include <malloc.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en sub-index1. */
+static void g_scan_sub_index1_modifier_class_init(GScanSubIndex1ModifierClass *);
+
+/* Initialise une instance de transmission en sub-index1. */
+static void g_scan_sub_index1_modifier_init(GScanSubIndex1Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sub_index1_modifier_dispose(GScanSubIndex1Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sub_index1_modifier_finalize(GScanSubIndex1Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_sub_index1_modifier_get_name(const GScanSubIndex1Modifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_sub_index1_modifier_transform(const GScanSubIndex1Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_sub_index1_modifier_get_path(const GScanSubIndex1Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte sub-index1. */
+G_DEFINE_TYPE(GScanSubIndex1Modifier, g_scan_sub_index1_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en sub-index1. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub_index1_modifier_class_init(GScanSubIndex1ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sub_index1_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_sub_index1_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_sub_index1_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_sub_index1_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_sub_index1_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en sub-index1. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub_index1_modifier_init(GScanSubIndex1Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub_index1_modifier_dispose(GScanSubIndex1Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_sub_index1_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub_index1_modifier_finalize(GScanSubIndex1Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_sub_index1_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des empreintes sub-index1. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_sub_index1_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SUB_INDEX1_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_sub_index1_modifier_get_name(const GScanSubIndex1Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("sub-index1");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_sub_index1_modifier_transform(const GScanSubIndex1Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ size_t k; /* Boucle de parcours #2 */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ binary->len = _src->len;
+ binary->data = malloc(binary->len);
+
+ for (k = 0; k < _src->len; k++)
+ binary->data[k] = _src->data[k] + k + 1;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_sub_index1_modifier_get_path(const GScanSubIndex1Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("sub-index1");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/sub-index1.h b/plugins/apihashing/custom/sub-index1.h
new file mode 100644
index 0000000..b2acc06
--- /dev/null
+++ b/plugins/apihashing/custom/sub-index1.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub-index1.h - prototypes pour la transormation en empreinte d'API sub-index1
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_SUB_INDEX1_H
+#define _PLUGINS_APIHASHING_CUSTOM_SUB_INDEX1_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_SUB_INDEX1_MODIFIER g_scan_sub_index1_modifier_get_type()
+#define G_SCAN_SUB_INDEX1_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SUB_INDEX1_MODIFIER, GScanSubIndex1Modifier))
+#define G_IS_SCAN_SUB_INDEX1_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SUB_INDEX1_MODIFIER))
+#define G_SCAN_SUB_INDEX1_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SUB_INDEX1_MODIFIER, GScanSubIndex1ModifierClass))
+#define G_IS_SCAN_SUB_INDEX1_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SUB_INDEX1_MODIFIER))
+#define G_SCAN_SUB_INDEX1_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SUB_INDEX1_MODIFIER, GScanSubIndex1ModifierClass))
+
+
+/* Transormation en empreinte d'API sub-index1 (instance) */
+typedef GApiHashModifier GScanSubIndex1Modifier;
+
+/* Transormation en empreinte d'API sub-index1 (classe) */
+typedef GApiHashModifierClass GScanSubIndex1ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte sub-index1. */
+GType g_scan_sub_index1_modifier_get_type(void);
+
+/* Construit un modificateur livrant des empreintes sub-index1. */
+GScanTokenModifier *g_scan_sub_index1_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_SUB_INDEX1_H */
diff --git a/plugins/apihashing/custom/sub42.c b/plugins/apihashing/custom/sub42.c
new file mode 100644
index 0000000..95bd49d
--- /dev/null
+++ b/plugins/apihashing/custom/sub42.c
@@ -0,0 +1,291 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub42.c - transormation en empreinte d'API sub42
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "sub42.h"
+
+
+#include <malloc.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en empreintes sub42. */
+static void g_scan_sub42_modifier_class_init(GScanSub42ModifierClass *);
+
+/* Initialise une instance de transmission en empreinte sub42. */
+static void g_scan_sub42_modifier_init(GScanSub42Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sub42_modifier_dispose(GScanSub42Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sub42_modifier_finalize(GScanSub42Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_sub42_modifier_get_name(const GScanSub42Modifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_sub42_modifier_transform(const GScanSub42Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_sub42_modifier_get_path(const GScanSub42Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en empreinte sub42. */
+G_DEFINE_TYPE(GScanSub42Modifier, g_scan_sub42_modifier, G_TYPE_API_HASH_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en empreintes sub42. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub42_modifier_class_init(GScanSub42ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sub42_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_sub42_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_sub42_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_sub42_modifier_transform;
+ modifier->get_path = (get_modifier_path)g_scan_sub42_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en empreinte sub42. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub42_modifier_init(GScanSub42Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub42_modifier_dispose(GScanSub42Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_sub42_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sub42_modifier_finalize(GScanSub42Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_sub42_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des empreintes sub42. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_sub42_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SUB42_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_sub42_modifier_get_name(const GScanSub42Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("sub42");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_sub42_modifier_transform(const GScanSub42Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ size_t k; /* Boucle de parcours #2 */
+
+ result = true;
+
+ *dcount = scount;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount; i++, binary++)
+ {
+ _src = src + i;
+
+ binary->len = _src->len;
+ binary->data = malloc(binary->len);
+
+ for (k = 0; k < _src->len; k++)
+ binary->data[k] = _src->data[k] + 0x42;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_sub42_modifier_get_path(const GScanSub42Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 0)
+ {
+ result = NULL;
+ (*index)--;
+ }
+
+ else
+ result = strdup("sub42");
+
+ return result;
+
+}
diff --git a/plugins/apihashing/custom/sub42.h b/plugins/apihashing/custom/sub42.h
new file mode 100644
index 0000000..8a11741
--- /dev/null
+++ b/plugins/apihashing/custom/sub42.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub42.h - prototypes pour la transormation en empreinte d'API sub42
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_CUSTOM_SUB42_H
+#define _PLUGINS_APIHASHING_CUSTOM_SUB42_H
+
+
+#include <glib-object.h>
+
+
+#include "../apihash.h"
+
+
+
+#define G_TYPE_SCAN_SUB42_MODIFIER g_scan_sub42_modifier_get_type()
+#define G_SCAN_SUB42_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SUB42_MODIFIER, GScanSub42Modifier))
+#define G_IS_SCAN_SUB42_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SUB42_MODIFIER))
+#define G_SCAN_SUB42_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SUB42_MODIFIER, GScanSub42ModifierClass))
+#define G_IS_SCAN_SUB42_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SUB42_MODIFIER))
+#define G_SCAN_SUB42_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SUB42_MODIFIER, GScanSub42ModifierClass))
+
+
+/* Transormation en empreinte d'API sub42 (instance) */
+typedef GApiHashModifier GScanSub42Modifier;
+
+/* Transormation en empreinte d'API sub42 (classe) */
+typedef GApiHashModifierClass GScanSub42ModifierClass;
+
+
+/* Indique le type défini pour une transormation en empreinte sub42. */
+GType g_scan_sub42_modifier_get_type(void);
+
+/* Construit un modificateur livrant des empreintes sub42. */
+GScanTokenModifier *g_scan_sub42_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_CUSTOM_SUB42_H */
diff --git a/plugins/apihashing/python/Makefile.am b/plugins/apihashing/python/Makefile.am
new file mode 100644
index 0000000..d94218d
--- /dev/null
+++ b/plugins/apihashing/python/Makefile.am
@@ -0,0 +1,20 @@
+
+noinst_LTLIBRARIES = libapihashingpython.la
+
+libapihashingpython_la_SOURCES = \
+ apihash.h apihash.c \
+ module.h module.c
+
+libapihashingpython_la_LIBADD = \
+ classics/libapihashingpythonclassics.la
+
+libapihashingpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libapihashingpython_la_SOURCES:%c=)
+
+
+SUBDIRS = classics
diff --git a/plugins/apihashing/python/apihash.c b/plugins/apihashing/python/apihash.c
new file mode 100644
index 0000000..a3ae519
--- /dev/null
+++ b/plugins/apihashing/python/apihash.c
@@ -0,0 +1,212 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.c - équivalent Python du fichier "plugins/encodings/rost/base64.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "apihash.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/scan/patterns/modifier.h>
+
+
+#include "../apihash.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(api_hash_modifier, G_TYPE_API_HASH_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_api_hash_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_api_hash_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define API_HASH_MODIFIER_DOC \
+ "The *ApiHashModifier* class is the base object for all algorithms" \
+ " involed in malwares and revolving API functions to call from" \
+ " a hash value.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ApiHashModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_api_hash_modifier_type(void)
+{
+ static PyMethodDef py_api_hash_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_api_hash_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_api_hash_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.apihashing.ApiHashModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = API_HASH_MODIFIER_DOC,
+
+ .tp_methods = py_api_hash_modifier_methods,
+ .tp_getset = py_api_hash_modifier_getseters,
+
+ .tp_init = py_api_hash_modifier_init,
+ .tp_new = py_api_hash_modifier_new,
+
+ };
+
+ return &py_api_hash_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....ApiHashModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_api_hash_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Base64Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_api_hash_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.apihashing");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_API_HASH_MODIFIER, 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 transformation par empreinte d'API. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_api_hash_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_api_hash_modifier_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 API hash modifier");
+ break;
+
+ case 1:
+ *((GApiHashModifier **)dst) = G_API_HASH_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/apihash.h b/plugins/apihashing/python/apihash.h
new file mode 100644
index 0000000..5474d49
--- /dev/null
+++ b/plugins/apihashing/python/apihash.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.h - équivalent Python du fichier "plugins/encodings/rost/base64.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H
+#define _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_api_hash_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.apihashing.ApiHashModifier'. */
+bool ensure_python_api_hash_modifier_is_registered(void);
+
+/* Tente de convertir en transformation par empreinte d'API. */
+int convert_to_api_hash_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H */
diff --git a/plugins/apihashing/python/classics/Makefile.am b/plugins/apihashing/python/classics/Makefile.am
new file mode 100644
index 0000000..316e13f
--- /dev/null
+++ b/plugins/apihashing/python/classics/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES = libapihashingpythonclassics.la
+
+libapihashingpythonclassics_la_SOURCES = \
+ crc32.h crc32.c \
+ djb2.h djb2.c \
+ module.h module.c \
+ ror13.h ror13.c
+
+libapihashingpythonclassics_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libapihashingpythonclassics_la_SOURCES:%c=)
diff --git a/plugins/apihashing/python/classics/crc32.c b/plugins/apihashing/python/classics/crc32.c
new file mode 100644
index 0000000..d7c6f7c
--- /dev/null
+++ b/plugins/apihashing/python/classics/crc32.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * crc32.c - équivalent Python du fichier "plugins/apihashing/classics/crc32.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "crc32.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../classics/crc32.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_crc32_modifier, G_TYPE_SCAN_CRC32_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_crc32_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_crc32_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_CRC32_MODIFIER_DOC \
+ "The *Crc32Modifier* class transforms a byte pattern into its" \
+ " crc32 encoded form.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Crc32Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_crc32_modifier_type(void)
+{
+ static PyMethodDef py_scan_crc32_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_crc32_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_crc32_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Crc32Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_CRC32_MODIFIER_DOC,
+
+ .tp_methods = py_scan_crc32_modifier_methods,
+ .tp_getset = py_scan_crc32_modifier_getseters,
+
+ .tp_init = py_scan_crc32_modifier_init,
+ .tp_new = py_scan_crc32_modifier_new,
+
+ };
+
+ return &py_scan_crc32_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....Crc32Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_crc32_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Crc32Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_crc32_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_CRC32_MODIFIER, 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 transformation en empreinte crc32. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_crc32_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_crc32_modifier_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 crc32 modifier");
+ break;
+
+ case 1:
+ *((GScanCrc32Modifier **)dst) = G_SCAN_CRC32_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/classics/crc32.h b/plugins/apihashing/python/classics/crc32.h
new file mode 100644
index 0000000..118a916
--- /dev/null
+++ b/plugins/apihashing/python/classics/crc32.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * crc32.h - équivalent Python du fichier "plugins/apihashing/classics/crc32.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_CRC32_H
+#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_CRC32_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_crc32_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Crc32Modifier'. */
+bool ensure_python_scan_crc32_modifier_is_registered(void);
+
+/* Tente de convertir en transformation en empreinte crc32. */
+int convert_to_scan_crc32_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_CRC32_H */
diff --git a/plugins/apihashing/python/classics/djb2.c b/plugins/apihashing/python/classics/djb2.c
new file mode 100644
index 0000000..f3d0844
--- /dev/null
+++ b/plugins/apihashing/python/classics/djb2.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * djb2.c - équivalent Python du fichier "plugins/apihashing/classics/djb2.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "djb2.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../classics/djb2.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_djb2_modifier, G_TYPE_SCAN_DJB2_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_djb2_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_djb2_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_DJB2_MODIFIER_DOC \
+ "The *Djb2Modifier* class transforms a byte pattern into its" \
+ " djb2 encoded form.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Djb2Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_djb2_modifier_type(void)
+{
+ static PyMethodDef py_scan_djb2_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_djb2_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_djb2_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Djb2Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_DJB2_MODIFIER_DOC,
+
+ .tp_methods = py_scan_djb2_modifier_methods,
+ .tp_getset = py_scan_djb2_modifier_getseters,
+
+ .tp_init = py_scan_djb2_modifier_init,
+ .tp_new = py_scan_djb2_modifier_new,
+
+ };
+
+ return &py_scan_djb2_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....Djb2Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_djb2_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Djb2Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_djb2_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_DJB2_MODIFIER, 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 transformation en empreinte djb2. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_djb2_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_djb2_modifier_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 djb2 modifier");
+ break;
+
+ case 1:
+ *((GScanDjb2Modifier **)dst) = G_SCAN_DJB2_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/classics/djb2.h b/plugins/apihashing/python/classics/djb2.h
new file mode 100644
index 0000000..b4086f8
--- /dev/null
+++ b/plugins/apihashing/python/classics/djb2.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * djb2.h - équivalent Python du fichier "plugins/apihashing/classics/djb2.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_DJB2_H
+#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_DJB2_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_djb2_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Djb2Modifier'. */
+bool ensure_python_scan_djb2_modifier_is_registered(void);
+
+/* Tente de convertir en transformation en empreinte djb2. */
+int convert_to_scan_djb2_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_DJB2_H */
diff --git a/plugins/apihashing/python/classics/module.c b/plugins/apihashing/python/classics/module.c
new file mode 100644
index 0000000..b00757a
--- /dev/null
+++ b/plugins/apihashing/python/classics/module.c
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire classics en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "crc32.h"
+#include "djb2.h"
+#include "ror13.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les modificateurs d'empreintes classiques pour ROST. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_apihashing_classics_modifiers(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_crc32_modifier_is_registered();
+ if (result) result = ensure_python_scan_djb2_modifier_is_registered();
+ if (result) result = ensure_python_scan_ror13_modifier_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/classics/module.h b/plugins/apihashing/python/classics/module.h
new file mode 100644
index 0000000..10c817d
--- /dev/null
+++ b/plugins/apihashing/python/classics/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire classics en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_MODULE_H
+#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Intègre les modificateurs d'empreintes classiques pour ROST. */
+bool register_apihashing_classics_modifiers(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_MODULE_H */
diff --git a/plugins/apihashing/python/classics/ror13.c b/plugins/apihashing/python/classics/ror13.c
new file mode 100644
index 0000000..429f7da
--- /dev/null
+++ b/plugins/apihashing/python/classics/ror13.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ror13.c - équivalent Python du fichier "plugins/apihashing/classics/ror13.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "ror13.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../classics/ror13.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_ror13_modifier, G_TYPE_SCAN_ROR13_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_ror13_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_ror13_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_ROR13_MODIFIER_DOC \
+ "The *Ror13Modifier* class transforms a byte pattern into its" \
+ " ror13 encoded form.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Ror13Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_ror13_modifier_type(void)
+{
+ static PyMethodDef py_scan_ror13_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_ror13_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_ror13_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Ror13Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_ROR13_MODIFIER_DOC,
+
+ .tp_methods = py_scan_ror13_modifier_methods,
+ .tp_getset = py_scan_ror13_modifier_getseters,
+
+ .tp_init = py_scan_ror13_modifier_init,
+ .tp_new = py_scan_ror13_modifier_new,
+
+ };
+
+ return &py_scan_ror13_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....Ror13Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_ror13_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Ror13Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_ror13_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_ROR13_MODIFIER, 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 transformation en empreinte ror13. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_ror13_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_ror13_modifier_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 ror13 modifier");
+ break;
+
+ case 1:
+ *((GScanRor13Modifier **)dst) = G_SCAN_ROR13_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/classics/ror13.h b/plugins/apihashing/python/classics/ror13.h
new file mode 100644
index 0000000..021a516
--- /dev/null
+++ b/plugins/apihashing/python/classics/ror13.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ror13.h - équivalent Python du fichier "plugins/apihashing/classics/ror13.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_ROR13_H
+#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_ROR13_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_ror13_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Ror13Modifier'. */
+bool ensure_python_scan_ror13_modifier_is_registered(void);
+
+/* Tente de convertir en transformation en empreinte ror13. */
+int convert_to_scan_ror13_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_ROR13_H */
diff --git a/plugins/apihashing/python/custom/Makefile.am b/plugins/apihashing/python/custom/Makefile.am
new file mode 100644
index 0000000..5fbb11f
--- /dev/null
+++ b/plugins/apihashing/python/custom/Makefile.am
@@ -0,0 +1,20 @@
+
+noinst_LTLIBRARIES = libapihashingpythoncustom.la
+
+libapihashingpythoncustom_la_SOURCES = \
+ add1505-shl5.h add1505-shl5.c \
+ enigma-murmur.h enigma-murmur.c \
+ imul21-add.h imul21-add.c \
+ imul83-add.h imul83-add.c \
+ module.h module.c \
+ sll1-add-hash32.h sll1-add-hash32.c \
+ sub-index1.h sub-index1.c \
+ sub42.h sub42.c
+
+libapihashingpythoncustom_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libapihashingpythoncustom_la_SOURCES:%c=)
diff --git a/plugins/apihashing/python/custom/add1505-shl5.c b/plugins/apihashing/python/custom/add1505-shl5.c
new file mode 100644
index 0000000..f70323c
--- /dev/null
+++ b/plugins/apihashing/python/custom/add1505-shl5.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * add1505-shl5.c - équivalent Python du fichier "plugins/apihashing/custom/add1505-shl5.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "add1505-shl5.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/add1505-shl5.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_add1505_shl5_modifier, G_TYPE_SCAN_ADD1505_SHL5_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_add1505_shl5_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_add1505_shl5_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_ADD1505_SHL5_MODIFIER_DOC \
+ "The *Add1505Shl5Modifier* class transforms a byte pattern" \
+ " using a add1505-shl5 hash.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Add1505Shl5Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_add1505_shl5_modifier_type(void)
+{
+ static PyMethodDef py_scan_add1505_shl5_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_add1505_shl5_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_add1505_shl5_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Add1505Shl5Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_ADD1505_SHL5_MODIFIER_DOC,
+
+ .tp_methods = py_scan_add1505_shl5_modifier_methods,
+ .tp_getset = py_scan_add1505_shl5_modifier_getseters,
+
+ .tp_init = py_scan_add1505_shl5_modifier_init,
+ .tp_new = py_scan_add1505_shl5_modifier_new,
+
+ };
+
+ return &py_scan_add1505_shl5_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet '...Add1505Shl5Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_add1505_shl5_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Add1505Shl5Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_add1505_shl5_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, 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 empreinte add1505-shl5. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_add1505_shl5_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_add1505_shl5_modifier_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 add1505-shl5 modifier");
+ break;
+
+ case 1:
+ *((GScanAdd1505Shl5Modifier **)dst) = G_SCAN_ADD1505_SHL5_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/add1505-shl5.h b/plugins/apihashing/python/custom/add1505-shl5.h
new file mode 100644
index 0000000..941d6ce
--- /dev/null
+++ b/plugins/apihashing/python/custom/add1505-shl5.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * add1505-shl5.h - équivalent Python du fichier "plugins/apihashing/custom/add1505-shl5.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_ADD1505_SHL5_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_ADD1505_SHL5_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_add1505_shl5_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Add1505Shl5Modifier'. */
+bool ensure_python_scan_add1505_shl5_modifier_is_registered(void);
+
+/* Tente de convertir en empreinte add1505-shl5. */
+int convert_to_scan_add1505_shl5_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_ADD1505_SHL5_H */
diff --git a/plugins/apihashing/python/custom/enigma-murmur.c b/plugins/apihashing/python/custom/enigma-murmur.c
new file mode 100644
index 0000000..f544f1a
--- /dev/null
+++ b/plugins/apihashing/python/custom/enigma-murmur.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enigma-murmur.c - équivalent Python du fichier "plugins/apihashing/custom/enigma-murmur.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "enigma-murmur.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/enigma-murmur.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_enigma_murmur_modifier, G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_enigma_murmur_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_enigma_murmur_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_ENIGMA_MURMUR_MODIFIER_DOC \
+ "The *EnigmaMurmurModifier* class transforms a byte pattern" \
+ " using a enigma-murmur hash.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " EnigmaMurmurModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_enigma_murmur_modifier_type(void)
+{
+ static PyMethodDef py_scan_enigma_murmur_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_enigma_murmur_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_enigma_murmur_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.EnigmaMurmurModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_ENIGMA_MURMUR_MODIFIER_DOC,
+
+ .tp_methods = py_scan_enigma_murmur_modifier_methods,
+ .tp_getset = py_scan_enigma_murmur_modifier_getseters,
+
+ .tp_init = py_scan_enigma_murmur_modifier_init,
+ .tp_new = py_scan_enigma_murmur_modifier_new,
+
+ };
+
+ return &py_scan_enigma_murmur_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet '...EnigmaMurmurModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_enigma_murmur_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type EnigmaMurmurModifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_enigma_murmur_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, 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 empreinte enigma-murmur. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_enigma_murmur_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_enigma_murmur_modifier_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 enigma-murmur modifier");
+ break;
+
+ case 1:
+ *((GScanEnigmaMurmurModifier **)dst) = G_SCAN_ENIGMA_MURMUR_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/enigma-murmur.h b/plugins/apihashing/python/custom/enigma-murmur.h
new file mode 100644
index 0000000..8435dae
--- /dev/null
+++ b/plugins/apihashing/python/custom/enigma-murmur.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enigma-murmur.h - équivalent Python du fichier "plugins/apihashing/custom/enigma-murmur.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_ENIGMA_MURMUR_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_ENIGMA_MURMUR_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_enigma_murmur_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.EnigmaMurmurModifier'. */
+bool ensure_python_scan_enigma_murmur_modifier_is_registered(void);
+
+/* Tente de convertir en empreinte enigma-murmur. */
+int convert_to_scan_enigma_murmur_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_ENIGMA_MURMUR_H */
diff --git a/plugins/apihashing/python/custom/imul21-add.c b/plugins/apihashing/python/custom/imul21-add.c
new file mode 100644
index 0000000..aadc6cc
--- /dev/null
+++ b/plugins/apihashing/python/custom/imul21-add.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul21-add.c - équivalent Python du fichier "plugins/apihashing/custom/imul21-add.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "imul21-add.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/imul21-add.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_imul21_add_modifier, G_TYPE_SCAN_IMUL21_ADD_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_imul21_add_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_imul21_add_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_IMUL21_ADD_MODIFIER_DOC \
+ "The *Sll1AddHash32Modifier* class transforms a byte pattern" \
+ " using a variation of the sll1 algorithm.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Sll1AddHash32Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_imul21_add_modifier_type(void)
+{
+ static PyMethodDef py_scan_imul21_add_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_imul21_add_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_imul21_add_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Imul21AddModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_IMUL21_ADD_MODIFIER_DOC,
+
+ .tp_methods = py_scan_imul21_add_modifier_methods,
+ .tp_getset = py_scan_imul21_add_modifier_getseters,
+
+ .tp_init = py_scan_imul21_add_modifier_init,
+ .tp_new = py_scan_imul21_add_modifier_new,
+
+ };
+
+ return &py_scan_imul21_add_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet '...Imul21AddModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_imul21_add_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Sll1AddHash32Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_imul21_add_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_IMUL21_ADD_MODIFIER, 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 empreinte imul21-add. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_imul21_add_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_imul21_add_modifier_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 imul21-add modifier");
+ break;
+
+ case 1:
+ *((GScanImul21AddModifier **)dst) = G_SCAN_IMUL21_ADD_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/imul21-add.h b/plugins/apihashing/python/custom/imul21-add.h
new file mode 100644
index 0000000..3fcc053
--- /dev/null
+++ b/plugins/apihashing/python/custom/imul21-add.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul21-add.h - équivalent Python du fichier "plugins/apihashing/custom/imul21-add.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL21_ADD_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL21_ADD_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_imul21_add_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Imul21AddModifier'. */
+bool ensure_python_scan_imul21_add_modifier_is_registered(void);
+
+/* Tente de convertir en empreinte imul21-add. */
+int convert_to_scan_imul21_add_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL21_ADD_H */
diff --git a/plugins/apihashing/python/custom/imul83-add.c b/plugins/apihashing/python/custom/imul83-add.c
new file mode 100644
index 0000000..5e2d929
--- /dev/null
+++ b/plugins/apihashing/python/custom/imul83-add.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul83-add.c - équivalent Python du fichier "plugins/apihashing/custom/imul83-add.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "imul83-add.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/imul83-add.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_imul83_add_modifier, G_TYPE_SCAN_IMUL83_ADD_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_imul83_add_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_imul83_add_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_IMUL83_ADD_MODIFIER_DOC \
+ "The *Sll1AddHash32Modifier* class transforms a byte pattern" \
+ " using a variation of the sll1 algorithm.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Sll1AddHash32Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_imul83_add_modifier_type(void)
+{
+ static PyMethodDef py_scan_imul83_add_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_imul83_add_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_imul83_add_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Imul83AddModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_IMUL83_ADD_MODIFIER_DOC,
+
+ .tp_methods = py_scan_imul83_add_modifier_methods,
+ .tp_getset = py_scan_imul83_add_modifier_getseters,
+
+ .tp_init = py_scan_imul83_add_modifier_init,
+ .tp_new = py_scan_imul83_add_modifier_new,
+
+ };
+
+ return &py_scan_imul83_add_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet '...Imul83AddModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_imul83_add_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Sll1AddHash32Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_imul83_add_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_IMUL83_ADD_MODIFIER, 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 empreinte imul83-add. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_imul83_add_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_imul83_add_modifier_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 imul83-add modifier");
+ break;
+
+ case 1:
+ *((GScanImul83AddModifier **)dst) = G_SCAN_IMUL83_ADD_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/imul83-add.h b/plugins/apihashing/python/custom/imul83-add.h
new file mode 100644
index 0000000..fd05136
--- /dev/null
+++ b/plugins/apihashing/python/custom/imul83-add.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * imul83-add.h - équivalent Python du fichier "plugins/apihashing/custom/imul83-add.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL83_ADD_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL83_ADD_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_imul83_add_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Imul83AddModifier'. */
+bool ensure_python_scan_imul83_add_modifier_is_registered(void);
+
+/* Tente de convertir en empreinte imul83-add. */
+int convert_to_scan_imul83_add_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL83_ADD_H */
diff --git a/plugins/apihashing/python/custom/module.c b/plugins/apihashing/python/custom/module.c
new file mode 100644
index 0000000..07107dd
--- /dev/null
+++ b/plugins/apihashing/python/custom/module.c
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire custom en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "add1505-shl5.h"
+#include "enigma-murmur.h"
+#include "imul21-add.h"
+#include "imul83-add.h"
+#include "sll1-add-hash32.h"
+#include "sub-index1.h"
+#include "sub42.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les modificateurs d'empreintes particulières à ROST. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_apihashing_custom_modifiers(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_add1505_shl5_modifier_is_registered();
+ if (result) result = ensure_python_scan_enigma_murmur_modifier_is_registered();
+ if (result) result = ensure_python_scan_imul21_add_modifier_is_registered();
+ if (result) result = ensure_python_scan_imul83_add_modifier_is_registered();
+ if (result) result = ensure_python_scan_sll1_add_hash32_modifier_is_registered();
+ if (result) result = ensure_python_scan_sub42_modifier_is_registered();
+ if (result) result = ensure_python_scan_sub_index1_modifier_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/module.h b/plugins/apihashing/python/custom/module.h
new file mode 100644
index 0000000..9073651
--- /dev/null
+++ b/plugins/apihashing/python/custom/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire custom en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_MODULE_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Intègre les modificateurs d'empreintes particulières à ROST. */
+bool register_apihashing_custom_modifiers(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_MODULE_H */
diff --git a/plugins/apihashing/python/custom/sll1-add-hash32.c b/plugins/apihashing/python/custom/sll1-add-hash32.c
new file mode 100644
index 0000000..c63fcf3
--- /dev/null
+++ b/plugins/apihashing/python/custom/sll1-add-hash32.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sll1-add-hash32.c - équivalent Python du fichier "plugins/apihashing/custom/sll1-add-hash32.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "sll1-add-hash32.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/sll1-add-hash32.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_sll1_add_hash32_modifier, G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_sll1_add_hash32_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_sll1_add_hash32_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_SLL1_ADD_HASH32_MODIFIER_DOC \
+ "The *Sll1AddHash32Modifier* class transforms a byte pattern" \
+ " using a variation of the sll1 algorithm.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Sll1AddHash32Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_sll1_add_hash32_modifier_type(void)
+{
+ static PyMethodDef py_scan_sll1_add_hash32_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_sll1_add_hash32_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_sll1_add_hash32_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Sll1AddHash32Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_SLL1_ADD_HASH32_MODIFIER_DOC,
+
+ .tp_methods = py_scan_sll1_add_hash32_modifier_methods,
+ .tp_getset = py_scan_sll1_add_hash32_modifier_getseters,
+
+ .tp_init = py_scan_sll1_add_hash32_modifier_init,
+ .tp_new = py_scan_sll1_add_hash32_modifier_new,
+
+ };
+
+ return &py_scan_sll1_add_hash32_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet '...Sll1AddHash32Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_sll1_add_hash32_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Sll1AddHash32Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_sll1_add_hash32_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, 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 empreinte sll1-add-hash32. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_sll1_add_hash32_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_sll1_add_hash32_modifier_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 sll1-add-hash32 modifier");
+ break;
+
+ case 1:
+ *((GScanSll1AddHash32Modifier **)dst) = G_SCAN_SLL1_ADD_HASH32_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/sll1-add-hash32.h b/plugins/apihashing/python/custom/sll1-add-hash32.h
new file mode 100644
index 0000000..bf11c34
--- /dev/null
+++ b/plugins/apihashing/python/custom/sll1-add-hash32.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sll1-add-hash32.h - équivalent Python du fichier "plugins/apihashing/custom/sll1-add-hash32.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_SLL1_ADD_HASH32_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_SLL1_ADD_HASH32_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_sll1_add_hash32_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Sll1AddHash32Modifier'. */
+bool ensure_python_scan_sll1_add_hash32_modifier_is_registered(void);
+
+/* Tente de convertir en empreinte sll1-add-hash32. */
+int convert_to_scan_sll1_add_hash32_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_SLL1_ADD_HASH32_H */
diff --git a/plugins/apihashing/python/custom/sub-index1.c b/plugins/apihashing/python/custom/sub-index1.c
new file mode 100644
index 0000000..e5c1487
--- /dev/null
+++ b/plugins/apihashing/python/custom/sub-index1.c
@@ -0,0 +1,213 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub-index1.c - équivalent Python du fichier "plugins/apihashing/custom/sub-index1.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "sub-index1.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/sub-index1.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_sub_index1_modifier, G_TYPE_SCAN_SUB_INDEX1_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_sub_index1_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_sub_index1_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_SUB_INDEX1_MODIFIER_DOC \
+ "The *SubIndex1Modifier* class produces the encrypted version" \
+ " of a byte pattern where the index of a byte is added to its" \
+ " value.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Sub-Index1Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_sub_index1_modifier_type(void)
+{
+ static PyMethodDef py_scan_sub_index1_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_sub_index1_modifier_getseters[] = {
+
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_sub_index1_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.SubIndex1Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_SUB_INDEX1_MODIFIER_DOC,
+
+ .tp_methods = py_scan_sub_index1_modifier_methods,
+ .tp_getset = py_scan_sub_index1_modifier_getseters,
+
+ .tp_init = py_scan_sub_index1_modifier_init,
+ .tp_new = py_scan_sub_index1_modifier_new,
+
+ };
+
+ return &py_scan_sub_index1_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....SubIndex1Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_sub_index1_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Sub-Index1Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_sub_index1_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_SUB_INDEX1_MODIFIER, 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 transformation en empreinte sub-index1.*
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_sub_index1_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_sub_index1_modifier_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 sub-index1 modifier");
+ break;
+
+ case 1:
+ *((GScanSubIndex1Modifier **)dst) = G_SCAN_SUB_INDEX1_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/sub-index1.h b/plugins/apihashing/python/custom/sub-index1.h
new file mode 100644
index 0000000..65186f3
--- /dev/null
+++ b/plugins/apihashing/python/custom/sub-index1.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub-index1.h - équivalent Python du fichier "plugins/apihashing/custom/sub-index1.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB_INDEX1_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB_INDEX1_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_sub_index1_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.SubIndex1Modifier'. */
+bool ensure_python_scan_sub_index1_modifier_is_registered(void);
+
+/* Tente de convertir en transformation en empreinte sub-index1. */
+int convert_to_scan_sub_index1_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB_INDEX1_H */
diff --git a/plugins/apihashing/python/custom/sub42.c b/plugins/apihashing/python/custom/sub42.c
new file mode 100644
index 0000000..238496d
--- /dev/null
+++ b/plugins/apihashing/python/custom/sub42.c
@@ -0,0 +1,212 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub42.c - équivalent Python du fichier "plugins/apihashing/custom/sub42.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "sub42.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../apihash.h"
+#include "../../custom/sub42.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_sub42_modifier, G_TYPE_SCAN_SUB42_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_sub42_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_sub42_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_SUB42_MODIFIER_DOC \
+ "The *Sub42Modifier* class produces the encrypted version of a" \
+ " byte pattern where 0x42 is added to each byte.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Sub42Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_sub42_modifier_type(void)
+{
+ static PyMethodDef py_scan_sub42_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_sub42_modifier_getseters[] = {
+
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_sub42_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Sub42Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_SUB42_MODIFIER_DOC,
+
+ .tp_methods = py_scan_sub42_modifier_methods,
+ .tp_getset = py_scan_sub42_modifier_getseters,
+
+ .tp_init = py_scan_sub42_modifier_init,
+ .tp_new = py_scan_sub42_modifier_new,
+
+ };
+
+ return &py_scan_sub42_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....Sub42Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_sub42_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Sub42Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_sub42_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_api_hash_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_SUB42_MODIFIER, 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 transformation en empreinte sub42. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_sub42_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_sub42_modifier_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 sub42 modifier");
+ break;
+
+ case 1:
+ *((GScanSub42Modifier **)dst) = G_SCAN_SUB42_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/custom/sub42.h b/plugins/apihashing/python/custom/sub42.h
new file mode 100644
index 0000000..ce3660a
--- /dev/null
+++ b/plugins/apihashing/python/custom/sub42.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * sub42.h - équivalent Python du fichier "plugins/apihashing/custom/sub42.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB42_H
+#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB42_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_sub42_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Sub42Modifier'. */
+bool ensure_python_scan_sub42_modifier_is_registered(void);
+
+/* Tente de convertir en transformation en empreinte sub42. */
+int convert_to_scan_sub42_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB42_H */
diff --git a/plugins/apihashing/python/module.c b/plugins/apihashing/python/module.c
new file mode 100644
index 0000000..588a0d8
--- /dev/null
+++ b/plugins/apihashing/python/module.c
@@ -0,0 +1,87 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire apihashing en tant que module
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "apihash.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.apihashing' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_apihashing_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_APIHASHING_DOC \
+ "apihashing is a module providing a few implementations" \
+ " of algorithms used to resolve API functions by hash."
+
+ static PyModuleDef py_chrysalide_apihashing_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.apihashing",
+ .m_doc = PYCHRYSALIDE_PLUGINS_APIHASHING_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins");
+
+ module = build_python_module(super, &py_chrysalide_apihashing_module);
+
+ result = (module != NULL);
+
+ if (result) result = ensure_python_api_hash_modifier_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/apihashing/python/module.h b/plugins/apihashing/python/module.h
new file mode 100644
index 0000000..fe628b9
--- /dev/null
+++ b/plugins/apihashing/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire apihashing en tant que module
+ *
+ * Copyright (C) 2020 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_APIHASHING_PYTHON_MODULE_H
+#define _PLUGINS_APIHASHING_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.apihashing' au module Python. */
+bool add_apihashing_module_to_python_module(void);
+
+
+
+#endif /* _PLUGINS_APIHASHING_PYTHON_MODULE_H */
diff --git a/plugins/arm/Makefile.am b/plugins/arm/Makefile.am
index a37cbbd..3470256 100644
--- a/plugins/arm/Makefile.am
+++ b/plugins/arm/Makefile.am
@@ -35,23 +35,25 @@ PYTHON3_SUBDIRS = python
endif
-libarm_la_SOURCES = \
- cond.h \
- context-int.h \
- context.h context.c \
- core.h core.c \
- instruction-int.h \
- instruction.h instruction.c \
- link.h link.c \
- processor-int.h \
- processor.h processor.c \
- register-int.h \
+libarm_la_SOURCES = \
+ cond.h \
+ context-int.h \
+ context.h context.c \
+ core.h core.c \
+ instruction-int.h \
+ instruction.h instruction.c \
+ link.h link.c \
+ processor-int.h \
+ processor.h processor.c \
+ register-int.h \
register.h register.c
-libarm_la_LIBADD = \
- $(PYTHON3_LIBADD) \
+libarm_la_LIBADD = \
+ $(PYTHON3_LIBADD) \
v7/libarmv7.la
+libarm_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libarm_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -63,9 +65,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarm_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
SUBDIRS = v7 $(PYTHON3_SUBDIRS)
diff --git a/plugins/arm/core.c b/plugins/arm/core.c
index c270c85..1c1c6bc 100644
--- a/plugins/arm/core.c
+++ b/plugins/arm/core.c
@@ -24,17 +24,16 @@
#include "core.h"
-#include <config.h>
#include <plugins/self.h>
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
#include "v7/core.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -66,7 +65,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
result = init_armv7_core();
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_arch_arm_module_to_python_module();
#endif
diff --git a/plugins/arm/instruction.c b/plugins/arm/instruction.c
index 4872aba..c42250f 100644
--- a/plugins/arm/instruction.c
+++ b/plugins/arm/instruction.c
@@ -29,6 +29,7 @@
#include <string.h>
+#include <analysis/db/misc/rlestr.h>
#include <common/extstr.h>
#include <core/logs.h>
@@ -62,6 +63,17 @@ static bool g_arm_instruction_serialize(GArmInstruction *, GAsmStorage *, packed
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_arm_instruction_load(GArmInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_arm_instruction_store(GArmInstruction *, GObjectStorage *, packed_buffer_t *);
+
+
+
/* Indique le type défini pour une représentation d'une instruction ARM. */
G_DEFINE_TYPE(GArmInstruction, g_arm_instruction, G_TYPE_ARCH_INSTRUCTION);
@@ -93,6 +105,9 @@ static void g_arm_instruction_class_init(GArmInstructionClass *klass)
instr->unserialize = (unserialize_instruction_fc)g_arm_instruction_unserialize;
instr->serialize = (serialize_instruction_fc)g_arm_instruction_serialize;
+ instr->load = (load_instruction_fc)g_arm_instruction_load;
+ instr->store = (store_instruction_fc)g_arm_instruction_store;
+
}
@@ -382,3 +397,109 @@ static bool g_arm_instruction_serialize(GArmInstruction *instr, GAsmStorage *sto
return result;
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
+* *
+* Description : Charge un contenu depuis une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_arm_instruction_load(GArmInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchInstructionClass *parent; /* Classe parente à consulter */
+ rle_string str; /* Chaîne à charger */
+ uleb128_t value; /* Valeur ULEB128 à charger */
+
+ parent = G_ARCH_INSTRUCTION_CLASS(g_arm_instruction_parent_class);
+
+ result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+ if (result)
+ {
+ setup_empty_rle_string(&str);
+
+ result = unpack_rle_string(&str, pbuf);
+
+ if (result)
+ {
+ result = (get_rle_string(&str) != NULL);
+
+ if (result)
+ result = g_arm_instruction_extend_keyword(instr, get_rle_string(&str));
+
+ exit_rle_string(&str);
+
+ }
+
+ }
+
+ if (result)
+ {
+ result = unpack_uleb128(&value, pbuf);
+
+ if (result)
+ instr->cond = value;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à remplir. *
+* *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_arm_instruction_store(GArmInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchInstructionClass *parent; /* Classe parente à consulter */
+ rle_string str; /* Chaîne à conserver */
+
+ parent = G_ARCH_INSTRUCTION_CLASS(g_arm_instruction_parent_class);
+
+ result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+ if (result)
+ {
+ init_static_rle_string(&str, instr->suffix);
+
+ result = pack_rle_string(&str, pbuf);
+
+ exit_rle_string(&str);
+
+ }
+
+ if (result)
+ result = pack_uleb128((uleb128_t []){ instr->cond }, pbuf);
+
+ return result;
+
+}
diff --git a/plugins/arm/python/Makefile.am b/plugins/arm/python/Makefile.am
index f09baee..931b2b9 100644
--- a/plugins/arm/python/Makefile.am
+++ b/plugins/arm/python/Makefile.am
@@ -1,15 +1,16 @@
noinst_LTLIBRARIES = libarmpython.la
-libarmpython_la_SOURCES = \
- instruction.h instruction.c \
- module.h module.c \
+libarmpython_la_SOURCES = \
+ instruction.h instruction.c \
+ module.h module.c \
processor.h processor.c
-libarmpython_la_LIBADD = \
+libarmpython_la_LIBADD = \
v7/libarmpythonv7.la
-libarmpython_la_LDFLAGS =
+libarmpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -17,9 +18,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarmpython_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = v7
diff --git a/plugins/arm/python/instruction.c b/plugins/arm/python/instruction.c
index 81fd132..8a37d92 100644
--- a/plugins/arm/python/instruction.c
+++ b/plugins/arm/python/instruction.c
@@ -93,17 +93,19 @@ PyTypeObject *get_python_arm_instruction_type(void)
bool register_python_arm_instruction(PyObject *module)
{
- PyTypeObject *py_arm_instruction_type; /* Type Python 'BinContent' */
+ PyTypeObject *type; /* Type Python 'ArmInstruction'*/
PyObject *dict; /* Dictionnaire du module */
- py_arm_instruction_type = get_python_arm_instruction_type();
+ type = get_python_arm_instruction_type();
- APPLY_ABSTRACT_FLAG(py_arm_instruction_type);
+ APPLY_ABSTRACT_FLAG(type);
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARM_INSTRUCTION,
- py_arm_instruction_type, get_python_arch_instruction_type()))
+ if (!ensure_python_arch_instruction_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ARM_INSTRUCTION, type))
return false;
return true;
diff --git a/plugins/arm/python/processor.c b/plugins/arm/python/processor.c
index 1681f52..6a31611 100644
--- a/plugins/arm/python/processor.c
+++ b/plugins/arm/python/processor.c
@@ -93,14 +93,17 @@ PyTypeObject *get_python_arm_processor_type(void)
bool register_python_arm_processor(PyObject *module)
{
- PyTypeObject *py_arm_processor_type; /* Type Python 'BinContent' */
+ PyTypeObject *type; /* Type Python 'ArmProcessor' */
PyObject *dict; /* Dictionnaire du module */
- py_arm_processor_type = get_python_arm_processor_type();
+ type = get_python_arm_processor_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARM_PROCESSOR, py_arm_processor_type, get_python_arch_processor_type()))
+ if (!ensure_python_arch_processor_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ARM_PROCESSOR, type))
return false;
return true;
diff --git a/plugins/arm/python/v7/Makefile.am b/plugins/arm/python/v7/Makefile.am
index 06dc4af..a350d90 100644
--- a/plugins/arm/python/v7/Makefile.am
+++ b/plugins/arm/python/v7/Makefile.am
@@ -1,20 +1,15 @@
noinst_LTLIBRARIES = libarmpythonv7.la
-libarmpythonv7_la_SOURCES = \
- instruction.h instruction.c \
- module.h module.c \
+libarmpythonv7_la_SOURCES = \
+ instruction.h instruction.c \
+ module.h module.c \
processor.h processor.c
-libarmpythonv7_la_LDFLAGS =
+libarmpythonv7_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarmpythonv7_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/arm/python/v7/instruction.c b/plugins/arm/python/v7/instruction.c
index 81b34c3..27171ac 100644
--- a/plugins/arm/python/v7/instruction.c
+++ b/plugins/arm/python/v7/instruction.c
@@ -83,7 +83,7 @@ PyTypeObject *get_python_armv7_instruction_type(void)
* *
* Paramètres : module = module dont la définition est à compléter. *
* *
-* Description : Prend en charge l'objet 'pychrysalide....arm.ArmInstruction'.*
+* Description : Prend en charge l'objet 'pychrysalide.....ArmV7Instruction'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -93,15 +93,16 @@ PyTypeObject *get_python_armv7_instruction_type(void)
bool register_python_armv7_instruction(PyObject *module)
{
- PyTypeObject *py_armv7_instruction_type;/* Type Python 'BinContent' */
+ PyTypeObject *type; /* Type 'ArmV7Instruction' */
PyObject *dict; /* Dictionnaire du module */
- py_armv7_instruction_type = get_python_armv7_instruction_type();
+ type = get_python_armv7_instruction_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARMV7_INSTRUCTION,
- py_armv7_instruction_type, get_python_arm_instruction_type()))
+ /* TODO : ensure get_python_arm_instruction_type() */
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ARMV7_INSTRUCTION, type))
return false;
return true;
diff --git a/plugins/arm/python/v7/processor.c b/plugins/arm/python/v7/processor.c
index 6a1e3f0..5d5ea5c 100644
--- a/plugins/arm/python/v7/processor.c
+++ b/plugins/arm/python/v7/processor.c
@@ -83,7 +83,7 @@ PyTypeObject *get_python_armv7_processor_type(void)
* *
* Paramètres : module = module dont la définition est à compléter. *
* *
-* Description : Prend en charge l'objet 'pychrysalide.arch.arm.ArmProcessor'.*
+* Description : Prend en charge l'objet 'pychrysalide.....ArmV7Processor'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -93,14 +93,16 @@ PyTypeObject *get_python_armv7_processor_type(void)
bool register_python_armv7_processor(PyObject *module)
{
- PyTypeObject *py_armv7_processor_type; /* Type Python 'BinContent' */
+ PyTypeObject *type; /* Type Python 'ArmV7Processor'*/
PyObject *dict; /* Dictionnaire du module */
- py_armv7_processor_type = get_python_armv7_processor_type();
+ type = get_python_armv7_processor_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARMV7_PROCESSOR, py_armv7_processor_type, get_python_arm_processor_type()))
+ /* TODO : ensure get_python_arm_processor_type() */
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ARMV7_PROCESSOR, type))
return false;
return true;
diff --git a/plugins/arm/register.c b/plugins/arm/register.c
index 5d24806..6a58d59 100644
--- a/plugins/arm/register.c
+++ b/plugins/arm/register.c
@@ -46,22 +46,22 @@ static void g_arm_register_dispose(GArmRegister *);
/* Procède à la libération totale de la mémoire. */
static void g_arm_register_finalize(GArmRegister *);
-/* Produit une empreinte à partir d'un registre. */
-static guint g_arm_register_hash(const GArmRegister *);
-/* Compare un registre avec un autre. */
-static int g_arm_register_compare(const GArmRegister *, const GArmRegister *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
+/* Produit une empreinte à partir d'un registre. */
+static guint g_arm_register_hash(const GArmRegister *);
+/* Compare un registre avec un autre. */
+static int g_arm_register_compare(const GArmRegister *, const GArmRegister *);
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_arm_register_unserialize(GArmRegister *, GAsmStorage *, packed_buffer_t *);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_arm_register_load(GArmRegister *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un registre dans une mémoire tampon. */
-static bool g_arm_register_serialize(const GArmRegister *, GAsmStorage *, packed_buffer_t *);
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_arm_register_store(GArmRegister *, GObjectStorage *, packed_buffer_t *);
@@ -88,20 +88,21 @@ G_DEFINE_TYPE(GArmRegister, g_arm_register, G_TYPE_ARCH_REGISTER);
static void g_arm_register_class_init(GArmRegisterClass *klass)
{
- GObjectClass *object_class; /* Autre version de la classe */
- GArchRegisterClass *reg_class; /* Classe de haut niveau */
+ GObjectClass *object; /* Autre version de la classe */
+ GArchRegisterClass *reg; /* Classe de haut niveau */
- object_class = G_OBJECT_CLASS(klass);
+ object = G_OBJECT_CLASS(klass);
- object_class->dispose = (GObjectFinalizeFunc/* ! */)g_arm_register_dispose;
- object_class->finalize = (GObjectFinalizeFunc)g_arm_register_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_arm_register_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_arm_register_finalize;
- reg_class = G_ARCH_REGISTER_CLASS(klass);
+ reg = G_ARCH_REGISTER_CLASS(klass);
- reg_class->hash = (reg_hash_fc)g_arm_register_hash;
- reg_class->compare = (reg_compare_fc)g_arm_register_compare;
- reg_class->unserialize = (reg_unserialize_fc)g_arm_register_unserialize;
- reg_class->serialize = (reg_serialize_fc)g_arm_register_serialize;
+ reg->hash = (reg_hash_fc)g_arm_register_hash;
+ reg->compare = (reg_compare_fc)g_arm_register_compare;
+
+ reg->load = (load_register_fc)g_arm_register_load;
+ reg->store = (store_register_fc)g_arm_register_store;
}
@@ -181,6 +182,12 @@ uint8_t g_arm_register_get_index(const GArmRegister *reg)
}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : reg = opérande à consulter pour le calcul. *
@@ -224,19 +231,13 @@ static int g_arm_register_compare(const GArmRegister *a, const GArmRegister *b)
}
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : reg = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
* *
-* Description : Charge un registre depuis une mémoire tampon. *
+* Description : Charge un contenu depuis une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -244,24 +245,17 @@ static int g_arm_register_compare(const GArmRegister *a, const GArmRegister *b)
* *
******************************************************************************/
-static GArchRegister *g_arm_register_unserialize(GArmRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_arm_register_load(GArmRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
{
- GArchRegister *result; /* Instance à retourner */
+ bool result; /* Bilan à retourner */
GArchRegisterClass *parent; /* Classe parente à consulter */
- /**
- * L'indice de registre est utilisé par les sous-classes pour la regénération
- * à partir du cache.
- *
- * Il est donc lu depuis le tempon avant l'appel à cette fonction, et est
- * ainsi déjà pris en compte.
- */
-
- result = G_ARCH_REGISTER(reg);
-
parent = G_ARCH_REGISTER_CLASS(g_arm_register_parent_class);
- result = parent->unserialize(result, storage, pbuf);
+ result = parent->load(G_ARCH_REGISTER(reg), storage, pbuf);
+
+ if (result)
+ result = extract_packed_buffer(pbuf, &reg->index, sizeof(uint8_t), true);
return result;
@@ -270,11 +264,11 @@ static GArchRegister *g_arm_register_unserialize(GArmRegister *reg, GAsmStorage
/******************************************************************************
* *
-* Paramètres : reg = registre d'architecture à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : reg = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un registre dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -282,20 +276,17 @@ static GArchRegister *g_arm_register_unserialize(GArmRegister *reg, GAsmStorage
* *
******************************************************************************/
-static bool g_arm_register_serialize(const GArmRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_arm_register_store(GArmRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchRegisterClass *parent; /* Classe parente à consulter */
- result = extend_packed_buffer(pbuf, &reg->index, sizeof(uint8_t), false);
-
- if (result)
- {
- parent = G_ARCH_REGISTER_CLASS(g_arm_register_parent_class);
+ parent = G_ARCH_REGISTER_CLASS(g_arm_register_parent_class);
- result = parent->serialize(G_ARCH_REGISTER(reg), storage, pbuf);
+ result = parent->store(G_ARCH_REGISTER(reg), storage, pbuf);
- }
+ if (result)
+ result = extend_packed_buffer(pbuf, &reg->index, sizeof(uint8_t), false);
return result;
diff --git a/plugins/arm/v7/Makefile.am b/plugins/arm/v7/Makefile.am
index 5d30876..d87373a 100644
--- a/plugins/arm/v7/Makefile.am
+++ b/plugins/arm/v7/Makefile.am
@@ -1,36 +1,35 @@
noinst_LTLIBRARIES = libarmv7.la
-libarmv7_la_SOURCES = \
- arm.h arm.c \
- context.h context.c \
- core.h core.c \
- fetch.h fetch.c \
- helpers.h \
- instruction.h instruction.c \
- link.h link.c \
- post.h post.c \
- processor.h processor.c \
- pseudo.h pseudo.c \
- register-int.h \
- register.h register.c \
- thumb_16.h thumb_16.c \
+libarmv7_la_SOURCES = \
+ arm.h arm.c \
+ context.h context.c \
+ core.h core.c \
+ fetch.h fetch.c \
+ helpers.h \
+ instruction.h instruction.c \
+ link.h link.c \
+ operand-int.h \
+ operand.h operand.c \
+ post.h post.c \
+ processor.h processor.c \
+ pseudo.h pseudo.c \
+ register-int.h \
+ register.h register.c \
+ thumb_16.h thumb_16.c \
thumb_32.h thumb_32.c
-libarmv7_la_LIBADD = \
- opcodes/libarmv7opcodes.la \
- operands/libarmv7operands.la \
+libarmv7_la_LIBADD = \
+ opcodes/libarmv7opcodes.la \
+ operands/libarmv7operands.la \
registers/libarmv7registers.la
+libarmv7_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarmv7_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
SUBDIRS = opdefs opcodes operands registers
diff --git a/plugins/arm/v7/instruction.c b/plugins/arm/v7/instruction.c
index 30a5bd8..eb4a082 100644
--- a/plugins/arm/v7/instruction.c
+++ b/plugins/arm/v7/instruction.c
@@ -97,6 +97,17 @@ static bool g_armv7_instruction_serialize(GArmV7Instruction *, GAsmStorage *, pa
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_instruction_load(GArmV7Instruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_instruction_store(GArmV7Instruction *, GObjectStorage *, packed_buffer_t *);
+
+
+
/* Indique le type défini pour une représentation d'une instruction ARMv7. */
G_DEFINE_TYPE(GArmV7Instruction, g_armv7_instruction, G_TYPE_ARM_INSTRUCTION);
@@ -132,6 +143,9 @@ static void g_armv7_instruction_class_init(GArmV7InstructionClass *klass)
instr->unserialize = (unserialize_instruction_fc)g_armv7_instruction_unserialize;
instr->serialize = (serialize_instruction_fc)g_armv7_instruction_serialize;
+ instr->load = (load_instruction_fc)g_armv7_instruction_load;
+ instr->store = (store_instruction_fc)g_armv7_instruction_store;
+
}
@@ -506,3 +520,98 @@ static bool g_armv7_instruction_serialize(GArmV7Instruction *instr, GAsmStorage
return result;
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
+* *
+* Description : Charge un contenu depuis une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_armv7_instruction_load(GArmV7Instruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchInstructionClass *parent; /* Classe parente à consulter */
+ uleb128_t value; /* Valeur ULEB128 à charger */
+ uint8_t boolean; /* Valeur booléenne */
+
+ parent = G_ARCH_INSTRUCTION_CLASS(g_armv7_instruction_parent_class);
+
+ result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+ if (result)
+ result = unpack_uleb128(&value, pbuf);
+
+ if (result)
+ instr->sid = value;
+
+ if (result)
+ result = extract_packed_buffer(pbuf, &instr->encoding, sizeof(char), false);
+
+ if (result)
+ {
+ result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
+
+ if (result)
+ instr->setflags = (boolean == 1 ? true : false);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à remplir. *
+* *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_armv7_instruction_store(GArmV7Instruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchInstructionClass *parent; /* Classe parente à consulter */
+ uint8_t boolean; /* Valeur booléenne */
+
+ parent = G_ARCH_INSTRUCTION_CLASS(g_armv7_instruction_parent_class);
+
+ result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+ if (result)
+ result = pack_uleb128((uleb128_t []){ instr->sid }, pbuf);
+
+ if (result)
+ result = extend_packed_buffer(pbuf, &instr->encoding, sizeof(char), false);
+
+ if (result)
+ {
+ boolean = (instr->setflags ? 1 : 0);
+ result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
+ }
+
+ return result;
+
+}
diff --git a/plugins/arm/v7/opcodes/Makefile.am b/plugins/arm/v7/opcodes/Makefile.am
index 7a35ff9..c7fa4cc 100644
--- a/plugins/arm/v7/opcodes/Makefile.am
+++ b/plugins/arm/v7/opcodes/Makefile.am
@@ -13,7 +13,7 @@ noinst_LTLIBRARIES = libarmv7opcodes.la
libarmv7opcodes_la_SOURCES = $(GENERATED_FILES)
-libarmv7opcodes_la_LIBADD =
+libarmv7opcodes_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
@@ -21,11 +21,6 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarmv7opcodes_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -I$(top_srcdir)/src
-
-
CLEANFILES = $(GENERATED_FILES)
dist-hook:
diff --git a/plugins/arm/v7/operand-int.h b/plugins/arm/v7/operand-int.h
new file mode 100644
index 0000000..1832c32
--- /dev/null
+++ b/plugins/arm/v7/operand-int.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand-int.h - prototypes pour la définition interne des opérandes ARMv7
+ *
+ * Copyright (C) 2021 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_ARM_V7_OPERAND_INT_H
+#define _PLUGINS_ARM_V7_OPERAND_INT_H
+
+
+#include "operand.h"
+
+
+#include <arch/operand-int.h>
+
+
+
+/* Définition générique d'un opérande ARMv7 (instance) */
+struct _GArmV7Operand
+{
+ GArchOperand parent; /* A laisser en premier */
+
+};
+
+/* Définition générique d'un opérande ARMv7 (classe) */
+struct _GArmV7OperandClass
+{
+ GArchOperandClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _PLUGINS_ARM_V7_OPERAND_INT_H */
diff --git a/plugins/arm/v7/operand.c b/plugins/arm/v7/operand.c
new file mode 100644
index 0000000..ad7b572
--- /dev/null
+++ b/plugins/arm/v7/operand.c
@@ -0,0 +1,188 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand.c - opérandes ARMv7
+ *
+ * Copyright (C) 2021 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 "operand.h"
+
+
+#include "operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
+/* Initialise la classe des affichages de boutisme. */
+static void g_armv7_operand_class_init(GArmV7OperandClass *);
+
+/* Initialise une instance d'affichage de boutisme. */
+static void g_armv7_operand_init(GArmV7Operand *);
+
+/* Supprime toutes les références externes. */
+static void g_armv7_operand_dispose(GArmV7Operand *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_armv7_operand_finalize(GArmV7Operand *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_operand_hash(const GArmV7Operand *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour une de domaine et d'accès. */
+G_DEFINE_TYPE(GArmV7Operand, g_armv7_operand, G_TYPE_ARCH_OPERAND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des affichages de boutisme. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_operand_class_init(GArmV7OperandClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GArchOperandClass *operand; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_operand_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_armv7_operand_finalize;
+
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
+ operand->hash = (operand_hash_fc)g_armv7_operand_hash;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'affichage de boutisme. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_operand_init(GArmV7Operand *operand)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_operand_dispose(GArmV7Operand *operand)
+{
+ G_OBJECT_CLASS(g_armv7_operand_parent_class)->dispose(G_OBJECT(operand));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_operand_finalize(GArmV7Operand *operand)
+{
+ G_OBJECT_CLASS(g_armv7_operand_parent_class)->finalize(G_OBJECT(operand));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
+* *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* *
+* Retour : Empreinte de l'élément représenté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static guint g_armv7_operand_hash(const GArmV7Operand *operand, bool lock)
+{
+ guint result; /* Valeur à retourner */
+ operand_extra_data_t *extra; /* Données insérées à modifier */
+ GArchOperandClass *class; /* Classe parente normalisée */
+
+ extra = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(operand));
+
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
+
+ class = G_ARCH_OPERAND_CLASS(g_armv7_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
+
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
+
+ return result;
+
+}
diff --git a/plugins/arm/v7/operand.h b/plugins/arm/v7/operand.h
new file mode 100644
index 0000000..8c80365
--- /dev/null
+++ b/plugins/arm/v7/operand.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand.h - prototypes pour les opérandes ARMv7
+ *
+ * Copyright (C) 2017-2018 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_ARM_V7_OPERAND_H
+#define _PLUGINS_ARM_V7_OPERAND_H
+
+
+#include <glib-object.h>
+
+
+#include <arch/operand.h>
+
+
+
+#define G_TYPE_ARMV7_OPERAND g_armv7_operand_get_type()
+#define G_ARMV7_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_OPERAND, GArmV7Operand))
+#define G_IS_ARMV7_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_OPERAND))
+#define G_ARMV7_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_OPERAND, GArmV7OperandClass))
+#define G_IS_ARMV7_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_OPERAND))
+#define G_ARMV7_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_OPERAND, GArmV7OperandClass))
+
+
+/* Définition générique d'un opérande ARMv7 (instance) */
+typedef struct _GArmV7Operand GArmV7Operand;
+
+/* Définition générique d'un opérande ARMv7 (classe) */
+typedef struct _GArmV7OperandClass GArmV7OperandClass;
+
+
+/* Indique le type défini par la GLib pour un opérande ARMv7. */
+GType g_armv7_operand_get_type(void);
+
+
+
+#endif /* _PLUGINS_ARM_V7_OPERAND_H */
diff --git a/plugins/arm/v7/operands/Makefile.am b/plugins/arm/v7/operands/Makefile.am
index 31f6a8a..fa7ab8b 100644
--- a/plugins/arm/v7/operands/Makefile.am
+++ b/plugins/arm/v7/operands/Makefile.am
@@ -1,26 +1,21 @@
noinst_LTLIBRARIES = libarmv7operands.la
-libarmv7operands_la_SOURCES = \
- estate.h estate.c \
- iflags.h iflags.c \
- it.h it.c \
- limitation.h limitation.c \
- maccess.h maccess.c \
- offset.h offset.c \
- register.h register.c \
- reglist.h reglist.c \
- rotation.h rotation.c \
+libarmv7operands_la_SOURCES = \
+ estate.h estate.c \
+ iflags.h iflags.c \
+ it.h it.c \
+ limitation.h limitation.c \
+ maccess.h maccess.c \
+ offset.h offset.c \
+ register.h register.c \
+ reglist.h reglist.c \
+ rotation.h rotation.c \
shift.h shift.c
-libarmv7operands_la_LIBADD =
+libarmv7operands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarmv7operands_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/arm/v7/operands/estate.c b/plugins/arm/v7/operands/estate.c
index a76b464..accde6d 100644
--- a/plugins/arm/v7/operands/estate.c
+++ b/plugins/arm/v7/operands/estate.c
@@ -24,18 +24,20 @@
#include "estate.h"
-#include <arch/operand-int.h>
-#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
/* Définition d'un opérande affichant le choix d'un boutisme (instance) */
struct _GArmV7EndianOperand
{
- GArchOperand parent; /* Instance parente */
-
- bool big; /* Grand boutisme à afficher ? */
+ GArmV7Operand parent; /* Instance parente */
};
@@ -43,7 +45,7 @@ struct _GArmV7EndianOperand
/* Définition d'un opérande affichant le choix d'un boutisme (classe) */
struct _GArmV7EndianOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -60,27 +62,23 @@ static void g_armv7_endian_operand_dispose(GArmV7EndianOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_endian_operand_finalize(GArmV7EndianOperand *);
-/* Compare un opérande avec un autre. */
-static int g_armv7_endian_operand_compare(const GArmV7EndianOperand *, const GArmV7EndianOperand *);
-/* Traduit un opérande en version humainement lisible. */
-static void g_armv7_endian_operand_print(const GArmV7EndianOperand *, GBufferLine *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
-
+/* Traduit un opérande en version humainement lisible. */
+static void g_armv7_endian_operand_print(const GArmV7EndianOperand *, GBufferLine *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_endian_operand_unserialize(GArmV7EndianOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_endian_operand_serialize(const GArmV7EndianOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour une endian de domaine et d'accès. */
-G_DEFINE_TYPE(GArmV7EndianOperand, g_armv7_endian_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7EndianOperand, g_armv7_endian_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -106,12 +104,8 @@ static void g_armv7_endian_operand_class_init(GArmV7EndianOperandClass *klass)
object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_endian_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_armv7_endian_operand_finalize;
- operand->compare = (operand_compare_fc)g_armv7_endian_operand_compare;
operand->print = (operand_print_fc)g_armv7_endian_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_endian_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_endian_operand_serialize;
-
}
@@ -173,53 +167,6 @@ static void g_armv7_endian_operand_finalize(GArmV7EndianOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
-* *
-* Description : Compare un opérande avec un autre. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int g_armv7_endian_operand_compare(const GArmV7EndianOperand *a, const GArmV7EndianOperand *b)
-{
- int result; /* Bilan à faire remonter */
-
- result = sort_boolean(a->big, b->big);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un opérande en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_armv7_endian_operand_print(const GArmV7EndianOperand *operand, GBufferLine *line)
-{
- if (operand->big)
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "BE", 2, RTT_KEY_WORD, NULL);
- else
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "LE", 2, RTT_KEY_WORD, NULL);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : big = indication sur le boutisme à représenter. *
* *
* Description : Crée une représentation de boutisme ARMv7. *
@@ -236,107 +183,38 @@ GArchOperand *g_armv7_endian_operand_new(bool big)
result = g_object_new(G_TYPE_ARMV7_ENDIAN_OPERAND, NULL);
- result->big = big;
+ if (big)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7ESOF_BIG);
return G_ARCH_OPERAND(result);
}
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique le type de boutisme représenté. *
-* *
-* Retour : Type de boutisme. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_armv7_endian_operand_is_big_endian(const GArmV7EndianOperand *operand)
-{
- return operand->big;
-
-}
-
-
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un opérande depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_armv7_endian_operand_unserialize(GArmV7EndianOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t big; /* Grand boutisme à afficher ? */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_endian_operand_parent_class);
-
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &big, sizeof(uint8_t), false);
-
- if (result)
- operand->big = (big == 1 ? true : false);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Traduit un opérande en version humainement lisible. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_endian_operand_serialize(const GArmV7EndianOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static void g_armv7_endian_operand_print(const GArmV7EndianOperand *operand, GBufferLine *line)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t big; /* Grand boutisme à afficher ? */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_endian_operand_parent_class);
-
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
-
- if (result)
- {
- big = (operand->big ? 1 : 0);
- result = extend_packed_buffer(pbuf, &big, sizeof(uint8_t), false);
- }
-
- return result;
+ if (g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ESOF_BIG))
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "BE", 2, RTT_KEY_WORD, NULL);
+ else
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "LE", 2, RTT_KEY_WORD, NULL);
}
diff --git a/plugins/arm/v7/operands/estate.h b/plugins/arm/v7/operands/estate.h
index d049357..9b75f9c 100644
--- a/plugins/arm/v7/operands/estate.h
+++ b/plugins/arm/v7/operands/estate.h
@@ -32,6 +32,14 @@
+/* Etats particuliers d'un opérande de valeur immédiate */
+typedef enum _A7EStateOpFlag
+{
+ A7ESOF_BIG = AOF_USER_FLAG(0), /* Grand boutisme à afficher ? */
+
+} A7EStateOpFlag;
+
+
#define G_TYPE_ARMV7_ENDIAN_OPERAND g_armv7_endian_operand_get_type()
#define G_ARMV7_ENDIAN_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_ENDIAN_OPERAND, GArmV7EndianOperand))
#define G_IS_ARMV7_ENDIAN_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_ENDIAN_OPERAND))
@@ -53,9 +61,6 @@ GType g_armv7_endian_operand_get_type(void);
/* Crée une représentation de boutisme ARMv7. */
GArchOperand *g_armv7_endian_operand_new(bool);
-/* Indique le type de boutisme représenté. */
-bool g_armv7_endian_operand_is_big_endian(const GArmV7EndianOperand *);
-
#endif /* _PLUGINS_ARM_V7_OPERANDS_ESTATE_H */
diff --git a/plugins/arm/v7/operands/iflags.c b/plugins/arm/v7/operands/iflags.c
index 019fd21..f0a5e07 100644
--- a/plugins/arm/v7/operands/iflags.c
+++ b/plugins/arm/v7/operands/iflags.c
@@ -24,19 +24,20 @@
#include "iflags.h"
-#include <arch/operand-int.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
/* Définition d'un opérande précisant un masque d'interruption ARMv7 (instance) */
struct _GArmV7IFlagsOperand
{
- GArchOperand parent; /* Instance parente */
-
- bool abort_bit; /* Interruption d'arrêt async. */
- bool irq_bit; /* Interruption IRQ */
- bool fiq_bit; /* Interruption FIQ */
+ GArmV7Operand parent; /* Instance parente */
};
@@ -44,7 +45,7 @@ struct _GArmV7IFlagsOperand
/* Définition d'un opérande précisant un masque d'interruption ARMv7 (classe) */
struct _GArmV7IFlagsOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -61,24 +62,22 @@ static void g_armv7_iflags_operand_dispose(GArmV7IFlagsOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_iflags_operand_finalize(GArmV7IFlagsOperand *);
-/* Traduit un opérande en version humainement lisible. */
-static void g_armv7_iflags_operand_print(const GArmV7IFlagsOperand *, GBufferLine *);
-
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Traduit un opérande en version humainement lisible. */
+static void g_armv7_iflags_operand_print(const GArmV7IFlagsOperand *, GBufferLine *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_iflags_operand_unserialize(GArmV7IFlagsOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_iflags_operand_serialize(const GArmV7IFlagsOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un opérande de masque d'interruption ARMv7. */
-G_DEFINE_TYPE(GArmV7IFlagsOperand, g_armv7_iflags_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7IFlagsOperand, g_armv7_iflags_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -107,9 +106,6 @@ static void g_armv7_iflags_operand_class_init(GArmV7IFlagsOperandClass *klass)
operand->print = (operand_print_fc)g_armv7_iflags_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_iflags_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_iflags_operand_serialize;
-
}
@@ -127,9 +123,6 @@ static void g_armv7_iflags_operand_class_init(GArmV7IFlagsOperandClass *klass)
static void g_armv7_iflags_operand_init(GArmV7IFlagsOperand *operand)
{
- operand->abort_bit = false;
- operand->irq_bit = false;
- operand->fiq_bit = false;
}
@@ -174,33 +167,6 @@ static void g_armv7_iflags_operand_finalize(GArmV7IFlagsOperand *operand)
/******************************************************************************
* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un opérande en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_armv7_iflags_operand_print(const GArmV7IFlagsOperand *operand, GBufferLine *line)
-{
- if (operand->abort_bit)
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "A", 1, RTT_REGISTER, NULL);
-
- if (operand->irq_bit)
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "I", 1, RTT_REGISTER, NULL);
-
- if (operand->fiq_bit)
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "F", 1, RTT_REGISTER, NULL);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : a = bit d'arrêt asynchrone. *
* i = bit d'interruption IRQ. *
* f = bit d'interruption FIQ. *
@@ -219,119 +185,48 @@ GArchOperand *g_armv7_iflags_operand_new(bool a, bool i, bool f)
result = g_object_new(G_TYPE_ARMV7_IFLAGS_OPERAND, NULL);
- result->abort_bit = a;
- result->irq_bit = i;
- result->fiq_bit = f;
+ if (a)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7IFOF_ABORT);
+
+ if (i)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7IFOF_IRQ);
+
+ if (f)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7IFOF_FIQ);
return G_ARCH_OPERAND(result);
}
+
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un opérande depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_armv7_iflags_operand_unserialize(GArmV7IFlagsOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_iflags_operand_parent_class);
-
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->abort_bit = (boolean == 1 ? true : false);
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->irq_bit = (boolean == 1 ? true : false);
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->fiq_bit = (boolean == 1 ? true : false);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Traduit un opérande en version humainement lisible. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_iflags_operand_serialize(const GArmV7IFlagsOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static void g_armv7_iflags_operand_print(const GArmV7IFlagsOperand *operand, GBufferLine *line)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_iflags_operand_parent_class);
-
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
-
- if (result)
- {
- boolean = (operand->abort_bit ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
-
- if (result)
- {
- boolean = (operand->irq_bit ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ if (g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7IFOF_ABORT))
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "A", 1, RTT_REGISTER, NULL);
- if (result)
- {
- boolean = (operand->fiq_bit ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ if (g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7IFOF_IRQ))
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "I", 1, RTT_REGISTER, NULL);
- return result;
+ if (g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7IFOF_FIQ))
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "F", 1, RTT_REGISTER, NULL);
}
diff --git a/plugins/arm/v7/operands/iflags.h b/plugins/arm/v7/operands/iflags.h
index c0155a1..a198c85 100644
--- a/plugins/arm/v7/operands/iflags.h
+++ b/plugins/arm/v7/operands/iflags.h
@@ -33,6 +33,16 @@
+/* Etats particuliers d'un opérande de valeur immédiate */
+typedef enum _A7IFlagsOpFlag
+{
+ A7IFOF_ABORT = AOF_USER_FLAG(0), /* Interruption d'arrêt async. */
+ A7IFOF_IRQ = AOF_USER_FLAG(1), /* Interruption IRQ */
+ A7IFOF_FIQ = AOF_USER_FLAG(2), /* Interruption FIQ */
+
+} A7IFlagsOpFlag;
+
+
#define G_TYPE_ARMV7_IFLAGS_OPERAND g_armv7_iflags_operand_get_type()
#define G_ARMV7_IFLAGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_IFLAGS_OPERAND, GArmV7IFlagsOperand))
#define G_IS_ARMV7_IFLAGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_IFLAGS_OPERAND))
diff --git a/plugins/arm/v7/operands/it.c b/plugins/arm/v7/operands/it.c
index 6fab598..46e1b4c 100644
--- a/plugins/arm/v7/operands/it.c
+++ b/plugins/arm/v7/operands/it.c
@@ -27,27 +27,55 @@
#include <assert.h>
-#include <arch/operand-int.h>
#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
-/* Définition d'un opérande organisant l'application d'une instruction IT (instance) */
-struct _GArmV7ITCondOperand
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _a7itcop_extra_data_t
{
- GArchOperand parent; /* Instance parente */
+ operand_extra_data_t parent; /* A laisser en premier */
ArmCondCode firstcond; /* Condition première */
uint8_t mask; /* Masque de l'interprétation */
+} a7itcop_extra_data_t;
+
+
+/* Définition d'un opérande organisant l'application d'une instruction IT (instance) */
+struct _GArmV7ITCondOperand
+{
+ GArmV7Operand parent; /* Instance parente */
+
};
+/**
+ * Accès aux informations éventuellement déportées.
+ */
+
+#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+
+# define GET_ARMV7_ITCOND_OP_EXTRA(op) ((a7itcop_extra_data_t *)&((GArchOperand *)op)->extra)
+
+#else
+
+# define GET_ARMV7_ITCOND_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7itcop_extra_data_t)
+
+#endif
+
+
/* Définition d'un opérande organisant l'application d'une instruction IT (classe) */
struct _GArmV7ITCondOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -64,27 +92,35 @@ static void g_armv7_itcond_operand_dispose(GArmV7ITCondOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_itcond_operand_finalize(GArmV7ITCondOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *, const GArmV7ITCondOperand *);
+static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *, const GArmV7ITCondOperand *, bool);
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_itcond_operand_print(const GArmV7ITCondOperand *, GBufferLine *);
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_itcond_operand_hash(const GArmV7ITCondOperand *, bool);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_itcond_operand_load(GArmV7ITCondOperand *, GObjectStorage *, packed_buffer_t *);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_itcond_operand_store(GArmV7ITCondOperand *, GObjectStorage *, packed_buffer_t *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_itcond_operand_unserialize(GArmV7ITCondOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_itcond_operand_serialize(const GArmV7ITCondOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour l'application d'une instruction IT. */
-G_DEFINE_TYPE(GArmV7ITCondOperand, g_armv7_itcond_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7ITCondOperand, g_armv7_itcond_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -105,16 +141,20 @@ static void g_armv7_itcond_operand_class_init(GArmV7ITCondOperandClass *klass)
GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_itcond_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_armv7_itcond_operand_finalize;
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
operand->compare = (operand_compare_fc)g_armv7_itcond_operand_compare;
+
operand->print = (operand_print_fc)g_armv7_itcond_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_itcond_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_itcond_operand_serialize;
+ operand->hash = (operand_hash_fc)g_armv7_itcond_operand_hash;
+
+ operand->load = (load_operand_fc)g_armv7_itcond_operand_load;
+ operand->store = (store_operand_fc)g_armv7_itcond_operand_store;
}
@@ -177,8 +217,100 @@ static void g_armv7_itcond_operand_finalize(GArmV7ITCondOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : firstcond = valeur brute de la condition d'exécution. *
+* mask = masque d'interprétation pour l'instruction. *
+* *
+* Description : Crée un opérande lié à une instruction IT. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_itcond_operand_new(uint8_t firstcond, uint8_t mask)
+{
+ GArmV7ITCondOperand *result; /* Structure à retourner */
+ a7itcop_extra_data_t *extra; /* Données insérées à modifier */
+
+ if (firstcond > ACC_NV)
+ return NULL;
+
+ result = g_object_new(G_TYPE_ARMV7_ITCOND_OPERAND, NULL);
+
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(result);
+
+ extra->firstcond = firstcond;
+ extra->mask = mask;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Fournit la condition associée à l'opérande. *
+* *
+* Retour : Condition classique pour ARMv7. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+ArmCondCode g_armv7_itcond_operand_get_firstcond(const GArmV7ITCondOperand *operand)
+{
+ ArmCondCode result; /* Condition à renvoyer */
+ a7itcop_extra_data_t *extra; /* Données insérées à modifier */
+
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(operand);
+
+ result = extra->firstcond;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Fournit le masque d'interprétation de la condition. *
+* *
+* Retour : Masque de bits. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+uint8_t g_armv7_itcond_operand_get_mask(const GArmV7ITCondOperand *operand)
+{
+ uint8_t result; /* Valeur à retourner */
+ a7itcop_extra_data_t *extra; /* Données insérées à modifier */
+
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(operand);
+
+ result = extra->mask;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -188,14 +320,38 @@ static void g_armv7_itcond_operand_finalize(GArmV7ITCondOperand *operand)
* *
******************************************************************************/
-static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *a, const GArmV7ITCondOperand *b)
+static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *a, const GArmV7ITCondOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
+ a7itcop_extra_data_t *ea; /* Données insérées à consulter*/
+ a7itcop_extra_data_t *eb; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+
+ ea = GET_ARMV7_ITCOND_OP_EXTRA(a);
+ eb = GET_ARMV7_ITCOND_OP_EXTRA(b);
+
+ if (lock)
+ {
+ LOCK_GOBJECT_EXTRA(ea);
+ LOCK_GOBJECT_EXTRA(eb);
+ }
+
+ result = sort_boolean(ea->firstcond, eb->firstcond);
- result = sort_boolean(a->firstcond, b->firstcond);
+ if (result == 0)
+ result = sort_unsigned_long(ea->mask, eb->mask);
if (result == 0)
- result = sort_unsigned_long(a->mask, b->mask);
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
+
+ if (lock)
+ {
+ UNLOCK_GOBJECT_EXTRA(eb);
+ UNLOCK_GOBJECT_EXTRA(ea);
+ }
return result;
@@ -217,9 +373,12 @@ static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *a, const GA
static void g_armv7_itcond_operand_print(const GArmV7ITCondOperand *operand, GBufferLine *line)
{
+ a7itcop_extra_data_t *extra; /* Données insérées à consulter*/
const char *kw; /* Mot clef à imprimer */
- switch (operand->firstcond)
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(operand);
+
+ switch (extra->firstcond)
{
case ACC_EQ: kw = "EQ"; break;
case ACC_NE: kw = "NE"; break;
@@ -253,51 +412,37 @@ static void g_armv7_itcond_operand_print(const GArmV7ITCondOperand *operand, GBu
/******************************************************************************
* *
-* Paramètres : firstcond = valeur brute de la condition d'exécution. *
-* mask = masque d'interprétation pour l'instruction. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Crée un opérande lié à une instruction IT. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_itcond_operand_new(uint8_t firstcond, uint8_t mask)
+static guint g_armv7_itcond_operand_hash(const GArmV7ITCondOperand *operand, bool lock)
{
- GArmV7ITCondOperand *result; /* Structure à retourner */
+ guint result; /* Valeur à retourner */
+ a7itcop_extra_data_t *extra; /* Données internes à manipuler*/
+ GArchOperandClass *class; /* Classe parente normalisée */
- if (firstcond > ACC_NV)
- return NULL;
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(operand);
- result = g_object_new(G_TYPE_ARMV7_ITCOND_OPERAND, NULL);
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- result->firstcond = firstcond;
- result->mask = mask;
+ class = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- return G_ARCH_OPERAND(result);
+ result ^= extra->firstcond;
-}
+ result ^= extra->mask;
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Fournit la condition associée à l'opérande. *
-* *
-* Retour : Condition classique pour ARMv7. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-ArmCondCode g_armv7_itcond_operand_get_firstcond(const GArmV7ITCondOperand *operand)
-{
- ArmCondCode result; /* Condition à renvoyer */
-
- result = operand->firstcond;
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
return result;
@@ -306,41 +451,11 @@ ArmCondCode g_armv7_itcond_operand_get_firstcond(const GArmV7ITCondOperand *oper
/******************************************************************************
* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Fournit le masque d'interprétation de la condition. *
-* *
-* Retour : Masque de bits. *
+* Paramètres : operand = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-uint8_t g_armv7_itcond_operand_get_mask(const GArmV7ITCondOperand *operand)
-{
- uint8_t result; /* Valeur à retourner */
-
- result = operand->mask;
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Charge un contenu depuis une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -348,20 +463,30 @@ uint8_t g_armv7_itcond_operand_get_mask(const GArmV7ITCondOperand *operand)
* *
******************************************************************************/
-static bool g_armv7_itcond_operand_unserialize(GArmV7ITCondOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_armv7_itcond_operand_load(GArmV7ITCondOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ uleb128_t value; /* Valeur ULEB128 à charger */
+ a7itcop_extra_data_t *extra; /* Données insérées à modifier */
parent = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class);
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extract_packed_buffer(pbuf, &operand->firstcond, sizeof(ArmCondCode), true);
+ {
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(operand);
- if (result)
- result = extract_packed_buffer(pbuf, &operand->mask, sizeof(uint8_t), false);
+ result = unpack_uleb128(&value, pbuf);
+
+ if (result)
+ extra->firstcond = value;
+
+ if (result)
+ result = extract_packed_buffer(pbuf, &extra->mask, sizeof(uint8_t), false);
+
+ }
return result;
@@ -370,11 +495,11 @@ static bool g_armv7_itcond_operand_unserialize(GArmV7ITCondOperand *operand, GAs
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -382,20 +507,26 @@ static bool g_armv7_itcond_operand_unserialize(GArmV7ITCondOperand *operand, GAs
* *
******************************************************************************/
-static bool g_armv7_itcond_operand_serialize(const GArmV7ITCondOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_armv7_itcond_operand_store(GArmV7ITCondOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ a7itcop_extra_data_t *extra; /* Données insérées à modifier */
parent = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extend_packed_buffer(pbuf, &operand->firstcond, sizeof(ArmCondCode), true);
+ {
+ extra = GET_ARMV7_ITCOND_OP_EXTRA(operand);
- if (result)
- result = extend_packed_buffer(pbuf, &operand->mask, sizeof(uint8_t), false);
+ result = pack_uleb128((uleb128_t []){ extra->firstcond }, pbuf);
+
+ if (result)
+ result = extend_packed_buffer(pbuf, &extra->mask, sizeof(uint8_t), false);
+
+ }
return result;
diff --git a/plugins/arm/v7/operands/limitation.c b/plugins/arm/v7/operands/limitation.c
index 0d29545..d9e11cf 100644
--- a/plugins/arm/v7/operands/limitation.c
+++ b/plugins/arm/v7/operands/limitation.c
@@ -26,28 +26,57 @@
#include <arch/operand-int.h>
#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
-/* Définition d'un opérande déterminant une limitation de domaine et d'accès (instance) */
-struct _GArmV7LimitationOperand
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _a7limop_extra_data_t
{
- GArchOperand parent; /* Instance parente */
+ operand_extra_data_t parent; /* A laisser en premier */
BarrierLimitationType type; /* Type de limitation */
+} a7limop_extra_data_t;
+
+
+/* Définition d'un opérande déterminant une limitation de domaine et d'accès (instance) */
+struct _GArmV7LimitationOperand
+{
+ GArmV7Operand parent; /* Instance parente */
+
};
/* Définition d'un opérande déterminant une limitation de domaine et d'accès (classe) */
struct _GArmV7LimitationOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
+/**
+ * Accès aux informations éventuellement déportées.
+ */
+
+#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+
+# define GET_ARMV7_LIMITATION_OP_EXTRA(op) ((a7limop_extra_data_t *)&((GArchOperand *)op)->extra)
+
+#else
+
+# define GET_ARMV7_LIMITATION_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7limop_extra_data_t)
+
+#endif
+
+
/* Initialise la classe des co-processeurs ARM. */
static void g_armv7_limitation_operand_class_init(GArmV7LimitationOperandClass *);
@@ -60,27 +89,35 @@ static void g_armv7_limitation_operand_dispose(GArmV7LimitationOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_limitation_operand_finalize(GArmV7LimitationOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_limitation_operand_compare(const GArmV7LimitationOperand *, const GArmV7LimitationOperand *);
+static int g_armv7_limitation_operand_compare(const GArmV7LimitationOperand *, const GArmV7LimitationOperand *, bool);
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *, GBufferLine *);
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_limitation_operand_hash(const GArmV7LimitationOperand *, bool);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_limitation_operand_load(GArmV7LimitationOperand *, GObjectStorage *, packed_buffer_t *);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
-
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_limitation_operand_store(GArmV7LimitationOperand *, GObjectStorage *, packed_buffer_t *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_limitation_operand_unserialize(GArmV7LimitationOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_limitation_operand_serialize(const GArmV7LimitationOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour une limitation de domaine et d'accès. */
-G_DEFINE_TYPE(GArmV7LimitationOperand, g_armv7_limitation_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7LimitationOperand, g_armv7_limitation_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -107,10 +144,13 @@ static void g_armv7_limitation_operand_class_init(GArmV7LimitationOperandClass *
object->finalize = (GObjectFinalizeFunc)g_armv7_limitation_operand_finalize;
operand->compare = (operand_compare_fc)g_armv7_limitation_operand_compare;
+
operand->print = (operand_print_fc)g_armv7_limitation_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_limitation_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_limitation_operand_serialize;
+ operand->hash = (operand_hash_fc)g_armv7_limitation_operand_hash;
+
+ operand->load = (load_operand_fc)g_armv7_limitation_operand_load;
+ operand->store = (store_operand_fc)g_armv7_limitation_operand_store;
}
@@ -173,8 +213,77 @@ static void g_armv7_limitation_operand_finalize(GArmV7LimitationOperand *operand
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : raw = valeur brute de la limitation à considérer. *
+* *
+* Description : Crée une représentation d'une limitation pour barrière. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_limitation_operand_new(uint8_t raw)
+{
+ GArmV7LimitationOperand *result; /* Structure à retourner */
+ a7limop_extra_data_t *extra; /* Données insérées à modifier */
+
+ result = g_object_new(G_TYPE_ARMV7_LIMITATION_OPERAND, NULL);
+
+ extra = GET_ARMV7_LIMITATION_OP_EXTRA(result);
+
+ if (raw < 0b0010 || raw > 0b1111)
+ extra->type = BLT_RESERVED;
+
+ else
+ extra->type = raw;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Indique le type de limitation représentée. *
+* *
+* Retour : Type de limitation d'accès et de domaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+BarrierLimitationType g_armv7_limitation_operand_get_value(const GArmV7LimitationOperand *operand)
+{
+ BarrierLimitationType result; /* Type à retourner */
+ a7limop_extra_data_t *extra; /* Données insérées à consulter*/
+
+ extra = GET_ARMV7_LIMITATION_OP_EXTRA(operand);
+
+ LOCK_GOBJECT_EXTRA(extra);
+
+ result = extra->type;
+
+ UNLOCK_GOBJECT_EXTRA(extra);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -184,11 +293,35 @@ static void g_armv7_limitation_operand_finalize(GArmV7LimitationOperand *operand
* *
******************************************************************************/
-static int g_armv7_limitation_operand_compare(const GArmV7LimitationOperand *a, const GArmV7LimitationOperand *b)
+static int g_armv7_limitation_operand_compare(const GArmV7LimitationOperand *a, const GArmV7LimitationOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
+ a7limop_extra_data_t *ea; /* Données insérées à consulter*/
+ a7limop_extra_data_t *eb; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
- result = sort_unsigned_long(a->type, b->type);
+ ea = GET_ARMV7_LIMITATION_OP_EXTRA(a);
+ eb = GET_ARMV7_LIMITATION_OP_EXTRA(b);
+
+ if (lock)
+ {
+ LOCK_GOBJECT_EXTRA(ea);
+ LOCK_GOBJECT_EXTRA(eb);
+ }
+
+ result = sort_unsigned_long(ea->type, eb->type);
+
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
+
+ if (lock)
+ {
+ UNLOCK_GOBJECT_EXTRA(eb);
+ UNLOCK_GOBJECT_EXTRA(ea);
+ }
return result;
@@ -210,7 +343,11 @@ static int g_armv7_limitation_operand_compare(const GArmV7LimitationOperand *a,
static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *operand, GBufferLine *line)
{
- switch (operand->type)
+ BarrierLimitationType type; /* Type porté par l'opérande */
+
+ type = g_armv7_limitation_operand_get_value(operand);
+
+ switch (type)
{
case BLT_SY:
g_buffer_line_append_text(line, DLC_ASSEMBLY, "SY", 2, RTT_KEY_WORD, NULL);
@@ -255,66 +392,48 @@ static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *oper
/******************************************************************************
* *
-* Paramètres : raw = valeur brute de la limitation à considérer. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Crée une représentation d'une limitation pour barrière. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_limitation_operand_new(uint8_t raw)
+static guint g_armv7_limitation_operand_hash(const GArmV7LimitationOperand *operand, bool lock)
{
- GArmV7LimitationOperand *result; /* Structure à retourner */
+ guint result; /* Valeur à retourner */
+ a7limop_extra_data_t *extra; /* Données internes à manipuler*/
+ GArchOperandClass *class; /* Classe parente normalisée */
- result = g_object_new(G_TYPE_ARMV7_LIMITATION_OPERAND, NULL);
+ extra = GET_ARMV7_LIMITATION_OP_EXTRA(operand);
- if (raw < 0b0010 || raw > 0b1111)
- result->type = BLT_RESERVED;
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- else
- result->type = raw;
+ class = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- return G_ARCH_OPERAND(result);
+ result ^= extra->type;
-}
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique le type de limitation représentée. *
-* *
-* Retour : Type de limitation d'accès et de domaine. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-BarrierLimitationType g_armv7_limitation_operand_get_value(const GArmV7LimitationOperand *operand)
-{
- return operand->type;
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Charge un contenu depuis une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -322,17 +441,27 @@ BarrierLimitationType g_armv7_limitation_operand_get_value(const GArmV7Limitatio
* *
******************************************************************************/
-static bool g_armv7_limitation_operand_unserialize(GArmV7LimitationOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_armv7_limitation_operand_load(GArmV7LimitationOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ a7limop_extra_data_t *extra; /* Données insérées à modifier */
+ uleb128_t value; /* Valeur ULEB128 à charger */
parent = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class);
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extract_packed_buffer(pbuf, &operand->type, sizeof(BarrierLimitationType), true);
+ {
+ extra = GET_ARMV7_LIMITATION_OP_EXTRA(operand);
+
+ result = unpack_uleb128(&value, pbuf);
+
+ if (result)
+ extra->type = value;
+
+ }
return result;
@@ -341,11 +470,11 @@ static bool g_armv7_limitation_operand_unserialize(GArmV7LimitationOperand *oper
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -353,17 +482,23 @@ static bool g_armv7_limitation_operand_unserialize(GArmV7LimitationOperand *oper
* *
******************************************************************************/
-static bool g_armv7_limitation_operand_serialize(const GArmV7LimitationOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_armv7_limitation_operand_store(GArmV7LimitationOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ a7limop_extra_data_t *extra; /* Données insérées à modifier */
parent = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extend_packed_buffer(pbuf, &operand->type, sizeof(BarrierLimitationType), true);
+ {
+ extra = GET_ARMV7_LIMITATION_OP_EXTRA(operand);
+
+ result = pack_uleb128((uleb128_t []){ extra->type }, pbuf);
+
+ }
return result;
diff --git a/plugins/arm/v7/operands/maccess.c b/plugins/arm/v7/operands/maccess.c
index 07f38a6..77d031f 100644
--- a/plugins/arm/v7/operands/maccess.c
+++ b/plugins/arm/v7/operands/maccess.c
@@ -29,24 +29,26 @@
#include <stdlib.h>
-#include <arch/operand-int.h>
#include <common/cpp.h>
-#include <common/sort.h>
+#include <core/columns.h>
#include <core/logs.h>
-#include <gtkext/gtkblockdisplay.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
/* Définition d'un opérande offrant un accès à la mémoire depuis une base (instance) */
struct _GArmV7MAccessOperand
{
- GArchOperand parent; /* Instance parente */
+ GArmV7Operand parent; /* Instance parente */
GArchOperand *base; /* Base de l'accès en mémoire */
GArchOperand *offset; /* Décalage pour l'adresse */
GArchOperand *shift; /* Décalage supplémentaire ? */
- bool post_indexed; /* Position du décalage */
- bool write_back; /* Mise à jour de la base */
};
@@ -54,7 +56,7 @@ struct _GArmV7MAccessOperand
/* Définition d'un opérande offrant un accès à la mémoire depuis une base (classe) */
struct _GArmV7MAccessOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -71,8 +73,13 @@ static void g_armv7_maccess_operand_dispose(GArmV7MAccessOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *, const GArmV7MAccessOperand *);
+static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *, const GArmV7MAccessOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *g_armv7_maccess_operand_find_inner_operand_path(const GArmV7MAccessOperand *, const GArchOperand *);
@@ -83,21 +90,24 @@ static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const G
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *, GBufferLine *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GArchOperand **g_armv7_maccess_operand_list_inner_instances(const GArmV7MAccessOperand *, size_t *);
+/* Met à jour une liste de candidats embarqués par un candidat. */
+static void g_armv7_maccess_operand_update_inner_instances(GArmV7MAccessOperand *, GArchOperand **, size_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_maccess_operand_hash(const GArmV7MAccessOperand *, bool);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_maccess_operand_unserialize(GArmV7MAccessOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_maccess_operand_serialize(const GArmV7MAccessOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un accès à la mémoire depuis une base. */
-G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -130,8 +140,12 @@ static void g_armv7_maccess_operand_class_init(GArmV7MAccessOperandClass *klass)
operand->print = (operand_print_fc)g_armv7_maccess_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_maccess_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_maccess_operand_serialize;
+ operand->list_inner = (operand_list_inners_fc)g_armv7_maccess_operand_list_inner_instances;
+ operand->update_inner = (operand_update_inners_fc)g_armv7_maccess_operand_update_inner_instances;
+ operand->hash = (operand_hash_fc)g_armv7_maccess_operand_hash;
+
+ operand->load = g_arch_operand_load_generic_fixed_3;
+ operand->store = g_arch_operand_store_generic_fixed;
}
@@ -171,14 +185,9 @@ static void g_armv7_maccess_operand_init(GArmV7MAccessOperand *operand)
static void g_armv7_maccess_operand_dispose(GArmV7MAccessOperand *operand)
{
- if (operand->base != NULL)
- g_object_unref(G_OBJECT(operand->base));
-
- if (operand->offset != NULL)
- g_object_unref(G_OBJECT(operand->offset));
-
- if (operand->shift != NULL)
- g_object_unref(G_OBJECT(operand->shift));
+ g_clear_object(&operand->base);
+ g_clear_object(&operand->offset);
+ g_clear_object(&operand->shift);
G_OBJECT_CLASS(g_armv7_maccess_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -206,8 +215,109 @@ static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : base = représente le registre de la base d'accès. *
+* offset = détermine le décalage entre l'adresse et la base. *
+* shift = opération de décalage pour jouer sur le décalage. *
+* post = précise la forme donnée au décalage à appliquer. *
+* wback = indique une mise à jour de la base après usage. *
+* *
+* Description : Crée un accès à la mémoire depuis une base et un décalage. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_new(GArchOperand *base, GArchOperand *offset, GArchOperand *shift, bool post, bool wback)
+{
+ GArmV7MAccessOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ARMV7_MACCESS_OPERAND, NULL);
+
+ result->base = base;
+ result->offset = offset;
+ result->shift = shift;
+
+ if (post)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7MAOF_POST_INDEXED);
+
+ if (wback)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7MAOF_WRITE_BACK);
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit la base d'un accès à la mémoire. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_get_base(const GArmV7MAccessOperand *operand)
+{
+ return operand->base;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit le décalage d'un accès à la mémoire depuis la base. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_get_offset(const GArmV7MAccessOperand *operand)
+{
+ return operand->offset;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit le décalage d'un décalage pour un accès mémoire. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_get_shift(const GArmV7MAccessOperand *operand)
+{
+ return operand->shift;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -217,25 +327,24 @@ static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *operand)
* *
******************************************************************************/
-static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *a, const GArmV7MAccessOperand *b)
+static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *a, const GArmV7MAccessOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
+ GArchOperandClass *class; /* Classe parente normalisée */
result = g_arch_operand_compare(a->base, b->base);
- if (result != 0) goto gamoc_done;
-
- result = sort_pointer(a->offset, b->offset, (__compar_fn_t)g_arch_operand_compare);
- if (result != 0) goto gamoc_done;
-
- result = sort_pointer(a->shift, b->shift, (__compar_fn_t)g_arch_operand_compare);
- if (result != 0) goto gamoc_done;
- result = sort_boolean(a->post_indexed, b->post_indexed);
- if (result != 0) goto gamoc_done;
+ if (result)
+ result = g_arch_operand_compare(a->offset, b->offset);
- result = sort_boolean(a->write_back, b->write_back);
+ if (result)
+ result = g_arch_operand_compare(a->shift, b->shift);
- gamoc_done:
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
return result;
@@ -392,11 +501,17 @@ static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const G
static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, GBufferLine *line)
{
+ bool post; /* Forme post-indexée ? */
+ bool wback; /* Ecriture après coup ? */
+
+ post = g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7MAOF_POST_INDEXED);
+ wback = g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7MAOF_WRITE_BACK);
+
g_buffer_line_append_text(line, DLC_ASSEMBLY, "[", 1, RTT_HOOK, NULL);
g_arch_operand_print(operand->base, line);
- if (operand->post_indexed)
+ if (post)
g_buffer_line_append_text(line, DLC_ASSEMBLY, "]", 1, RTT_HOOK, NULL);
if (operand->offset != NULL)
@@ -417,10 +532,10 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, G
}
- if (!operand->post_indexed)
+ if (!post)
g_buffer_line_append_text(line, DLC_ASSEMBLY, "]", 1, RTT_HOOK, NULL);
- if (operand->post_indexed && operand->write_back)
+ if (post && wback)
g_buffer_line_append_text(line, DLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL);
}
@@ -428,306 +543,169 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, G
/******************************************************************************
* *
-* Paramètres : base = représente le registre de la base d'accès. *
-* offset = détermine le décalage entre l'adresse et la base. *
-* shift = opération de décalage pour jouer sur le décalage. *
-* post = précise la forme donnée au décalage à appliquer. *
-* wback = indique une mise à jour de la base après usage. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Crée un accès à la mémoire depuis une base et un décalage. *
+* Description : Fournit une liste de candidats embarqués par un candidat. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Liste de candidats internes ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_maccess_operand_new(GArchOperand *base, GArchOperand *offset, GArchOperand *shift, bool post, bool wback)
+static GArchOperand **g_armv7_maccess_operand_list_inner_instances(const GArmV7MAccessOperand *operand, size_t *count)
{
- GArmV7MAccessOperand *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_ARMV7_MACCESS_OPERAND, NULL);
-
- result->base = base;
- result->offset = offset;
- result->shift = shift;
-
- result->post_indexed = post;
- result->write_back = wback;
-
- return G_ARCH_OPERAND(result);
-
-}
+ GArchOperand **result; /* Instances à retourner */
+ size_t idx; /* Indice de traitement */
+ *count = 1;
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit la base d'un accès à la mémoire. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_maccess_operand_get_base(const GArmV7MAccessOperand *operand)
-{
- return operand->base;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit le décalage d'un accès à la mémoire depuis la base. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_maccess_operand_get_offset(const GArmV7MAccessOperand *operand)
-{
- return operand->offset;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit le décalage d'un décalage pour un accès mémoire. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_maccess_operand_get_shift(const GArmV7MAccessOperand *operand)
-{
- return operand->shift;
+ if (operand->offset != NULL)
+ (*count)++;
-}
+ if (operand->shift != NULL)
+ (*count)++;
+ result = malloc(*count * sizeof(GArchOperand *));
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique si le décalage est post-indexé. *
-* *
-* Retour : Statut des opérations menées. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result[0] = operand->base;
+ g_object_ref(G_OBJECT(result[0]));
-bool g_armv7_maccess_operand_is_post_indexed(const GArmV7MAccessOperand *operand)
-{
- return operand->post_indexed;
+ if (operand->offset != NULL)
+ {
+ result[1] = operand->offset;
+ g_object_ref(G_OBJECT(result[1]));
-}
+ idx = 2;
+ }
+ else
+ idx = 1;
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique si la base est mise à jour après usage. *
-* *
-* Retour : Statut des opérations menées. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (operand->shift != NULL)
+ {
+ result[idx] = operand->shift;
+ g_object_ref(G_OBJECT(result[idx]));
+ }
-bool g_armv7_maccess_operand_has_to_write_back(const GArmV7MAccessOperand *operand)
-{
- return operand->write_back;
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* instances = liste de candidats internes devenus singletons. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Met à jour une liste de candidats embarqués par un candidat. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_maccess_operand_unserialize(GArmV7MAccessOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static void g_armv7_maccess_operand_update_inner_instances(GArmV7MAccessOperand *operand, GArchOperand **instances, size_t count)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- GArchOperand *subop; /* Sous-opérande à intégrer */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
-
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- {
- subop = g_arch_operand_load(storage, format, pbuf);
-
- if (subop == NULL)
- result = false;
-
- else
- operand->base = subop;
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result && boolean == 1)
- {
- subop = g_arch_operand_load(storage, format, pbuf);
+#ifndef NDEBUG
+ size_t idx_check; /* Décompte des éléments utiles*/
+#endif
+ size_t i; /* Boucle de parcours */
- if (subop == NULL)
- result = false;
+#ifndef NDEBUG
+ idx_check = 1;
- else
- operand->offset = subop;
+ if (operand->offset != NULL)
+ (idx_check)++;
- }
+ if (operand->shift != NULL)
+ (idx_check)++;
- }
+ assert(count == idx_check);
+#endif
- if (result)
+ for (i = 0; i < count; i++)
{
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result && boolean == 1)
+ switch (i)
{
- subop = g_arch_operand_load(storage, format, pbuf);
-
- if (subop == NULL)
- result = false;
-
- else
- operand->shift = subop;
+ case 0:
+ g_clear_object(&operand->base);
+ operand->base = instances[i];
+ break;
+
+ case 1:
+ if (operand->offset != NULL)
+ {
+ g_clear_object(&operand->offset);
+ operand->offset = instances[i];
+ }
+ else
+ {
+ assert(count == 2);
+
+ g_clear_object(&operand->shift);
+ operand->shift = instances[i];
+
+ }
+ break;
+
+ case 2:
+ g_clear_object(&operand->shift);
+ operand->shift = instances[i];
+ break;
}
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->post_indexed = (boolean == 1 ? true : false);
+ g_object_ref(G_OBJECT(instances[i]));
}
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->write_back = (boolean == 1 ? true : false);
-
- }
-
- return result;
-
}
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_maccess_operand_serialize(const GArmV7MAccessOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static guint g_armv7_maccess_operand_hash(const GArmV7MAccessOperand *operand, bool lock)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
-
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
-
- if (result)
- result = g_arch_operand_store(operand->base, storage, pbuf);
-
- if (result)
- {
- if (operand->offset == NULL)
- result = extend_packed_buffer(pbuf, (uint8_t []) { 0 }, sizeof(uint8_t), false);
-
- else
- {
- result = extend_packed_buffer(pbuf, (uint8_t []) { 1 }, sizeof(uint8_t), false);
+ guint result; /* Valeur à retourner */
+ operand_extra_data_t *extra; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+ size_t count; /* Quantité d'éléments utiles */
- if (result)
- result = g_arch_operand_store(operand->offset, storage, pbuf);
+ extra = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(operand));
- }
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- }
+ class = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- if (result)
- {
- if (operand->shift == NULL)
- result = extend_packed_buffer(pbuf, (uint8_t []) { 0 }, sizeof(uint8_t), false);
+ count = 1;
- else
- {
- result = extend_packed_buffer(pbuf, (uint8_t []) { 1 }, sizeof(uint8_t), false);
-
- if (result)
- result = g_arch_operand_store(operand->shift, storage, pbuf);
-
- }
+ if (operand->offset != NULL)
+ (count)++;
- }
+ if (operand->shift != NULL)
+ (count)++;
- if (result)
- {
- boolean = (operand->post_indexed ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ result ^= count;
- if (result)
- {
- boolean = (operand->write_back ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
return result;
diff --git a/plugins/arm/v7/operands/maccess.h b/plugins/arm/v7/operands/maccess.h
index bc80cfa..eb39c30 100644
--- a/plugins/arm/v7/operands/maccess.h
+++ b/plugins/arm/v7/operands/maccess.h
@@ -36,6 +36,15 @@
+/* Etats particuliers d'un opérande de valeur immédiate */
+typedef enum _A7MAccessOpFlag
+{
+ A7MAOF_POST_INDEXED = AOF_USER_FLAG(0), /* Position du décalage */
+ A7MAOF_WRITE_BACK = AOF_USER_FLAG(1), /* Mise à jour de la base */
+
+} A7MAccessOpFlag;
+
+
#define G_TYPE_ARMV7_MACCESS_OPERAND g_armv7_maccess_operand_get_type()
#define G_ARMV7_MACCESS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_MACCESS_OPERAND, GArmV7MAccessOperand))
#define G_IS_ARMV7_MACCESS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_MACCESS_OPERAND))
diff --git a/plugins/arm/v7/operands/offset.c b/plugins/arm/v7/operands/offset.c
index 615e296..724523d 100644
--- a/plugins/arm/v7/operands/offset.c
+++ b/plugins/arm/v7/operands/offset.c
@@ -24,22 +24,26 @@
#include "offset.h"
+#include <assert.h>
#include <stdio.h>
#include <string.h>
-#include <arch/operand-int.h>
-#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
/* Définition d'un opérande visant à constituer un décalage relatif ARMv7 (instance) */
struct _GArmV7OffsetOperand
{
- GArchOperand parent; /* Instance parente */
+ GArmV7Operand parent; /* Instance parente */
- bool positive; /* Sens du décalage */
GArchOperand *value; /* Valeur du décalage */
};
@@ -48,7 +52,7 @@ struct _GArmV7OffsetOperand
/* Définition d'un opérande visant à constituer un décalage relatif ARMv7 (classe) */
struct _GArmV7OffsetOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -65,8 +69,13 @@ static void g_armv7_offset_operand_dispose(GArmV7OffsetOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_offset_operand_finalize(GArmV7OffsetOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_offset_operand_compare(const GArmV7OffsetOperand *, const GArmV7OffsetOperand *);
+static int g_armv7_offset_operand_compare(const GArmV7OffsetOperand *, const GArmV7OffsetOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *g_armv7_offset_operand_find_inner_operand_path(const GArmV7OffsetOperand *, const GArchOperand *);
@@ -77,21 +86,21 @@ static GArchOperand *g_armv7_offset_operand_get_inner_operand_from_path(const GA
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_offset_operand_print(const GArmV7OffsetOperand *, GBufferLine *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GArchOperand **g_armv7_offset_operand_list_inner_instances(const GArmV7OffsetOperand *, size_t *);
-
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Met à jour une liste de candidats embarqués par un candidat. */
+static void g_armv7_offset_operand_update_inner_instances(GArmV7OffsetOperand *, GArchOperand **, size_t);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_offset_operand_unserialize(GArmV7OffsetOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_offset_operand_serialize(const GArmV7OffsetOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un décalage relatif ARMv7. */
-G_DEFINE_TYPE(GArmV7OffsetOperand, g_armv7_offset_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7OffsetOperand, g_armv7_offset_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -124,8 +133,11 @@ static void g_armv7_offset_operand_class_init(GArmV7OffsetOperandClass *klass)
operand->print = (operand_print_fc)g_armv7_offset_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_offset_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_offset_operand_serialize;
+ operand->list_inner = (operand_list_inners_fc)g_armv7_offset_operand_list_inner_instances;
+ operand->update_inner = (operand_update_inners_fc)g_armv7_offset_operand_update_inner_instances;
+
+ operand->load = g_arch_operand_load_generic_fixed_1;
+ operand->store = g_arch_operand_store_generic_fixed;
}
@@ -163,8 +175,7 @@ static void g_armv7_offset_operand_init(GArmV7OffsetOperand *operand)
static void g_armv7_offset_operand_dispose(GArmV7OffsetOperand *operand)
{
- if (operand->value != NULL)
- g_object_unref(G_OBJECT(operand->value));
+ g_clear_object(&operand->value);
G_OBJECT_CLASS(g_armv7_offset_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -192,8 +203,69 @@ static void g_armv7_offset_operand_finalize(GArmV7OffsetOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : positive = indique si la quantité doit être ajoutée ou non. *
+* value = valeur du décalage à appliquer. *
+* *
+* Description : Crée un décalage selon un sens et une valeur donnés. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_offset_operand_new(bool positive, GArchOperand *value)
+{
+ GArmV7OffsetOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ARMV7_OFFSET_OPERAND, NULL);
+
+ if (positive)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7OOF_POSITIVE);
+
+ result->value = value;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit la valeur utilisée pour un décalage. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_offset_operand_get_value(const GArmV7OffsetOperand *operand)
+{
+ GArchOperand *result; /* Instance à retourner */
+
+ result = operand->value;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -203,16 +275,18 @@ static void g_armv7_offset_operand_finalize(GArmV7OffsetOperand *operand)
* *
******************************************************************************/
-static int g_armv7_offset_operand_compare(const GArmV7OffsetOperand *a, const GArmV7OffsetOperand *b)
+static int g_armv7_offset_operand_compare(const GArmV7OffsetOperand *a, const GArmV7OffsetOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
-
- result = sort_boolean(a->positive, b->positive);
- if (result != 0) goto gaooc_done;
+ GArchOperandClass *class; /* Classe parente normalisée */
result = g_arch_operand_compare(a->value, b->value);
- gaooc_done:
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_offset_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
return result;
@@ -299,7 +373,7 @@ static GArchOperand *g_armv7_offset_operand_get_inner_operand_from_path(const GA
static void g_armv7_offset_operand_print(const GArmV7OffsetOperand *operand, GBufferLine *line)
{
- if (!operand->positive)
+ if (!g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7OOF_POSITIVE))
g_buffer_line_append_text(line, DLC_ASSEMBLY, "-", 1, RTT_KEY_WORD, NULL);
g_arch_operand_print(operand->value, line);
@@ -309,127 +383,27 @@ static void g_armv7_offset_operand_print(const GArmV7OffsetOperand *operand, GBu
/******************************************************************************
* *
-* Paramètres : positive = indique si la quantité doit être ajoutée ou non. *
-* value = valeur du décalage à appliquer. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Crée un décalage selon un sens et une valeur donnés. *
+* Description : Fournit une liste de candidats embarqués par un candidat. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Liste de candidats internes ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_offset_operand_new(bool positive, GArchOperand *value)
+static GArchOperand **g_armv7_offset_operand_list_inner_instances(const GArmV7OffsetOperand *operand, size_t *count)
{
- GArmV7OffsetOperand *result; /* Structure à retourner */
+ GArchOperand **result; /* Instances à retourner */
- result = g_object_new(G_TYPE_ARMV7_OFFSET_OPERAND, NULL);
+ *count = 1;
- result->positive = positive;
- result->value = value;
+ result = malloc(*count * sizeof(GArchOperand *));
- return G_ARCH_OPERAND(result);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique le sens du décalage représenté. *
-* *
-* Retour : Indication d'ajout ou de retrait. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_armv7_offset_operand_is_positive(const GArmV7OffsetOperand *operand)
-{
- return operand->positive;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit la valeur utilisée pour un décalage. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_offset_operand_get_value(const GArmV7OffsetOperand *operand)
-{
- GArchOperand *result; /* Instance à retourner */
-
- result = operand->value;
-
- g_object_ref(G_OBJECT(result));
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un opérande depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_armv7_offset_operand_unserialize(GArmV7OffsetOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- GArchOperand *value; /* Valeur à intégrer */
- uint8_t positive; /* Sens du décalage */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_offset_operand_parent_class);
-
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- {
- value = g_arch_operand_load(storage, format, pbuf);
-
- if (value == NULL)
- result = false;
-
- else
- operand->value = value;
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &positive, sizeof(uint8_t), false);
-
- if (result)
- operand->positive = (positive == 1 ? true : false);
-
- }
+ result[0] = operand->value;
+ g_object_ref(G_OBJECT(result[0]));
return result;
@@ -438,37 +412,25 @@ static bool g_armv7_offset_operand_unserialize(GArmV7OffsetOperand *operand, GAs
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* instances = liste de candidats internes devenus singletons. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Met à jour une liste de candidats embarqués par un candidat. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_offset_operand_serialize(const GArmV7OffsetOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static void g_armv7_offset_operand_update_inner_instances(GArmV7OffsetOperand *operand, GArchOperand **instances, size_t count)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t positive; /* Sens du décalage */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_offset_operand_parent_class);
+ assert(count == 1);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ g_clear_object(&operand->value);
- if (result)
- {
- positive = (operand->positive ? 1 : 0);
- result = extend_packed_buffer(pbuf, &positive, sizeof(uint8_t), false);
- }
-
- if (result)
- result = g_arch_operand_store(operand->value, storage, pbuf);
-
- return result;
+ operand->value = instances[0];
+ g_object_ref(G_OBJECT(instances[0]));
}
diff --git a/plugins/arm/v7/operands/offset.h b/plugins/arm/v7/operands/offset.h
index aa4df5e..0b5f1bf 100644
--- a/plugins/arm/v7/operands/offset.h
+++ b/plugins/arm/v7/operands/offset.h
@@ -36,6 +36,14 @@
+/* Etats particuliers d'un opérande de valeur immédiate */
+typedef enum _A7OffOpFlag
+{
+ A7OOF_POSITIVE = AOF_USER_FLAG(0), /* Sens du décalage */
+
+} A7OffOpFlag;
+
+
#define G_TYPE_ARMV7_OFFSET_OPERAND g_armv7_offset_operand_get_type()
#define G_ARMV7_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_OFFSET_OPERAND, GArmV7OffsetOperand))
#define G_IS_ARMV7_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_OFFSET_OPERAND))
@@ -57,9 +65,6 @@ GType g_armv7_offset_operand_get_type(void);
/* Crée un décalage selon un sens et une valeur donnés. */
GArchOperand *g_armv7_offset_operand_new(bool, GArchOperand *);
-/* Indique le sens du décalage représenté. */
-bool g_armv7_offset_operand_is_positive(const GArmV7OffsetOperand *);
-
/* Founit la valeur utilisée pour un décalage. */
GArchOperand *g_armv7_offset_operand_get_value(const GArmV7OffsetOperand *);
diff --git a/plugins/arm/v7/operands/register.c b/plugins/arm/v7/operands/register.c
index bfbaa70..fa5b887 100644
--- a/plugins/arm/v7/operands/register.c
+++ b/plugins/arm/v7/operands/register.c
@@ -25,20 +25,29 @@
#include <arch/operands/register-int.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <common/sort.h>
+#include <core/columns.h>
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _a7regop_extra_data_t
+{
+ operand_extra_data_t parent; /* A laisser en premier */
+
+ uint8_t alignment; /* Eventuel alignement */
+
+} a7regop_extra_data_t;
+
+
/* Définition d'un opérande visant un registre ARMv7 (instance) */
struct _GArmV7RegisterOperand
{
GRegisterOperand parent; /* Instance parente */
- unsigned int alignment; /* Eventuel alignement */
- bool has_alignment; /* Validité du champ */
-
- bool write_back; /* Mise à jour du registre ? */
-
};
@@ -50,6 +59,21 @@ struct _GArmV7RegisterOperandClass
};
+/**
+ * Accès aux informations éventuellement déportées.
+ */
+
+#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+
+# define GET_ARMV7_REGISTER_OP_EXTRA(op) ((a7regop_extra_data_t *)&((GArchOperand *)op)->extra)
+
+#else
+
+# define GET_ARMV7_REGISTER_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7regop_extra_data_t)
+
+#endif
+
+
/* Initialise la classe des opérandes de registre ARMv7. */
static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *);
@@ -62,20 +86,31 @@ static void g_armv7_register_operand_dispose(GArmV7RegisterOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Compare un opérande avec un autre. */
+static int g_armv7_register_operand_compare(const GArmV7RegisterOperand *, const GArmV7RegisterOperand *, bool);
+
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_register_operand_print(const GArmV7RegisterOperand *, GBufferLine *);
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_register_operand_hash(const GArmV7RegisterOperand *, bool);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_register_operand_load(GArmV7RegisterOperand *, GObjectStorage *, packed_buffer_t *);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_register_operand_store(GArmV7RegisterOperand *, GObjectStorage *, packed_buffer_t *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un opérande de registre ARMv7. */
@@ -106,10 +141,14 @@ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *klas
operand = G_ARCH_OPERAND_CLASS(klass);
+ operand->compare = (operand_compare_fc)g_armv7_register_operand_compare;
+
operand->print = (operand_print_fc)g_armv7_register_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_register_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_register_operand_serialize;
+ operand->hash = (operand_hash_fc)g_armv7_register_operand_hash;
+
+ operand->load = (load_operand_fc)g_armv7_register_operand_load;
+ operand->store = (store_operand_fc)g_armv7_register_operand_store;
}
@@ -128,7 +167,6 @@ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *klas
static void g_armv7_register_operand_init(GArmV7RegisterOperand *operand)
{
- operand->write_back = false;
}
@@ -173,33 +211,6 @@ static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *operand)
/******************************************************************************
* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un opérande en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_armv7_register_operand_print(const GArmV7RegisterOperand *operand, GBufferLine *line)
-{
- GArchOperandClass *parent; /* Classe parente */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
-
- parent->print(G_ARCH_OPERAND(operand), line);
-
- if (operand->write_back)
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : reg = registre déjà en place. *
* *
* Description : Crée un opérande visant un registre ARMv7. *
@@ -238,9 +249,20 @@ GArchOperand *g_armv7_register_operand_new(GArmV7Register *reg)
void g_armv7_register_operand_define_alignement(GArmV7RegisterOperand *operand, unsigned int align)
{
- operand->alignment = align;
+ a7regop_extra_data_t *extra; /* Données internes à manipuler*/
+
+ extra = GET_ARMV7_REGISTER_OP_EXTRA(operand);
+
+ LOCK_GOBJECT_EXTRA(extra);
+
+ extra->alignment = align;
- operand->has_alignment = true;
+ if (align > 0)
+ _g_arch_operand_set_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT, false);
+ else
+ _g_arch_operand_unset_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT, false);
+
+ UNLOCK_GOBJECT_EXTRA(extra);
}
@@ -260,83 +282,159 @@ void g_armv7_register_operand_define_alignement(GArmV7RegisterOperand *operand,
void g_armv7_register_operand_write_back(GArmV7RegisterOperand *operand, bool wback)
{
- operand->write_back = wback;
+ g_arch_operand_set_flag(G_ARCH_OPERAND(operand), A7ROF_WRITE_BACK);
}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = opérande représentant un registre. *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Indique si le registre est mis à jour après coup. *
+* Description : Compare un opérande avec un autre. *
* *
-* Retour : Evolution du registre. *
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_armv7_register_operand_is_written_back(const GArmV7RegisterOperand *operand)
+static int g_armv7_register_operand_compare(const GArmV7RegisterOperand *a, const GArmV7RegisterOperand *b, bool lock)
{
- bool result; /* Statut à retourner */
+ int result; /* Bilan à faire remonter */
+ a7regop_extra_data_t *ea; /* Données insérées à consulter*/
+ a7regop_extra_data_t *eb; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+
+ ea = GET_ARMV7_REGISTER_OP_EXTRA(a);
+ eb = GET_ARMV7_REGISTER_OP_EXTRA(b);
- result = operand->write_back;
+ if (lock)
+ {
+ LOCK_GOBJECT_EXTRA(ea);
+ LOCK_GOBJECT_EXTRA(eb);
+ }
+
+ result = sort_unsigned_long(ea->alignment, eb->alignment);
+
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
+
+ if (lock)
+ {
+ UNLOCK_GOBJECT_EXTRA(eb);
+ UNLOCK_GOBJECT_EXTRA(ea);
+ }
return result;
}
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_register_operand_print(const GArmV7RegisterOperand *operand, GBufferLine *line)
+{
+ GArchOperandClass *parent; /* Classe parente */
+
+ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
+
+ parent->print(G_ARCH_OPERAND(operand), line);
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
+ if (g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_WRITE_BACK))
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL);
+
+}
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static guint g_armv7_register_operand_hash(const GArmV7RegisterOperand *operand, bool lock)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
+ guint result; /* Valeur à retourner */
+ a7regop_extra_data_t *extra; /* Données internes à manipuler*/
+ GArchOperandClass *class; /* Classe parente normalisée */
- parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
+ extra = GET_ARMV7_REGISTER_OP_EXTRA(operand);
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
+ class = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- if (result)
- operand->has_alignment = (boolean == 1 ? true : false);
+ result ^= extra->alignment;
- }
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
+* *
+* Description : Charge un contenu depuis une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- if (result && operand->has_alignment)
- result = extract_packed_buffer(pbuf, &operand->alignment, sizeof(unsigned int), true);
+static bool g_armv7_register_operand_load(GArmV7RegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+ a7regop_extra_data_t *extra; /* Données internes à manipuler*/
+
+ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
+
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
- if (result)
+ if (result && g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT))
{
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
+ extra = GET_ARMV7_REGISTER_OP_EXTRA(operand);
- if (result)
- operand->write_back = (boolean == 1 ? true : false);
+ result = extract_packed_buffer(pbuf, &extra->alignment, sizeof(uint8_t), false);
}
@@ -347,11 +445,11 @@ static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand,
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -359,29 +457,22 @@ static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand,
* *
******************************************************************************/
-static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_armv7_register_operand_store(GArmV7RegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
+ a7regop_extra_data_t *extra; /* Données internes à manipuler*/
parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
- if (result)
+ if (result && g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT))
{
- boolean = (operand->has_alignment ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ extra = GET_ARMV7_REGISTER_OP_EXTRA(operand);
- if (result && operand->has_alignment)
- result = extend_packed_buffer(pbuf, &operand->alignment, sizeof(unsigned int), true);
+ result = extend_packed_buffer(pbuf, &extra->alignment, sizeof(uint8_t), false);
- if (result)
- {
- boolean = (operand->write_back ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
}
return result;
diff --git a/plugins/arm/v7/operands/register.h b/plugins/arm/v7/operands/register.h
index 241c101..26e03c0 100644
--- a/plugins/arm/v7/operands/register.h
+++ b/plugins/arm/v7/operands/register.h
@@ -36,6 +36,15 @@
+/* Etats particuliers d'un opérande de valeur immédiate */
+typedef enum _A7RegOpFlag
+{
+ A7ROF_HAS_ALIGNMENT = AOF_USER_FLAG(0), /* Validité de l'alignement */
+ A7ROF_WRITE_BACK = AOF_USER_FLAG(1), /* Mise à jour du registre ? */
+
+} A7RegOpFlag;
+
+
#define G_TYPE_ARMV7_REGISTER_OPERAND g_armv7_register_operand_get_type()
#define G_ARMV7_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_REGISTER_OPERAND, GArmV7RegisterOperand))
#define G_IS_ARMV7_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_REGISTER_OPERAND))
@@ -63,9 +72,6 @@ void g_armv7_register_operand_define_alignement(GArmV7RegisterOperand *, unsigne
/* Détermine si le registre est mis à jour après l'opération. */
void g_armv7_register_operand_write_back(GArmV7RegisterOperand *, bool);
-/* Indique si le registre est mis à jour après coup. */
-bool g_armv7_register_operand_is_written_back(const GArmV7RegisterOperand *);
-
#endif /* _PLUGINS_ARM_V7_OPERANDS_REGISTER_H */
diff --git a/plugins/arm/v7/operands/reglist.c b/plugins/arm/v7/operands/reglist.c
index 9b9a817..b525f28 100644
--- a/plugins/arm/v7/operands/reglist.c
+++ b/plugins/arm/v7/operands/reglist.c
@@ -28,21 +28,24 @@
#include <malloc.h>
-#include <arch/operand-int.h>
#include <arch/register.h>
#include <arch/storage.h>
#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
#include "../registers/basic.h"
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
/* Définition d'un opérande listant une série de registres ARM (instance) */
struct _GArmV7RegListOperand
{
- GArchOperand parent; /* Instance parente */
+ GArmV7Operand parent; /* Instance parente */
GArmV7Register **registers; /* Liste de registres intégrés */
size_t count; /* Taille de cette liste */
@@ -53,7 +56,7 @@ struct _GArmV7RegListOperand
/* Définition d'un opérande listant une série de registres ARM (classe) */
struct _GArmV7RegListOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -70,27 +73,35 @@ static void g_armv7_reglist_operand_dispose(GArmV7RegListOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_reglist_operand_finalize(GArmV7RegListOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_reglist_operand_compare(const GArmV7RegListOperand *, const GArmV7RegListOperand *);
+static int g_armv7_reglist_operand_compare(const GArmV7RegListOperand *, const GArmV7RegListOperand *, bool);
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *, GBufferLine *);
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_reglist_operand_hash(const GArmV7RegListOperand *, bool);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_reglist_operand_load(GArmV7RegListOperand *, GObjectStorage *, packed_buffer_t *);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
-
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_reglist_operand_store(GArmV7RegListOperand *, GObjectStorage *, packed_buffer_t *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_reglist_operand_serialize(const GArmV7RegListOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour une liste de registres ARM. */
-G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -119,8 +130,10 @@ static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *klass)
operand->compare = (operand_compare_fc)g_armv7_reglist_operand_compare;
operand->print = (operand_print_fc)g_armv7_reglist_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_reglist_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_reglist_operand_serialize;
+ operand->hash = (operand_hash_fc)g_armv7_reglist_operand_hash;
+
+ operand->load = (load_operand_fc)g_armv7_reglist_operand_load;
+ operand->store = (store_operand_fc)g_armv7_reglist_operand_store;
}
@@ -162,7 +175,7 @@ static void g_armv7_reglist_operand_dispose(GArmV7RegListOperand *operand)
size_t i; /* Boucle de parcours */
for (i = 0; i < operand->count; i++)
- g_object_unref(G_OBJECT(operand->registers[i]));
+ g_clear_object(&operand->registers[i]);
G_OBJECT_CLASS(g_armv7_reglist_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -193,88 +206,6 @@ static void g_armv7_reglist_operand_finalize(GArmV7RegListOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
-* *
-* Description : Compare un opérande avec un autre. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int g_armv7_reglist_operand_compare(const GArmV7RegListOperand *a, const GArmV7RegListOperand *b)
-{
- int result; /* Bilan à faire remonter */
- size_t i; /* Boucle de parcours */
- GArchRegister *ra; /* Registre de la liste A */
- GArchRegister *rb; /* Registre de la liste B */
-
- /* Création de l'objet... */
- if (b == NULL)
- {
- result = 1;
- goto garoc_done;
- }
-
- result = sort_unsigned_long(a->count, b->count);
- if (result != 0) goto garoc_done;
-
- for (i = 0; i < a->count && result == 0; i++)
- {
- ra = G_ARCH_REGISTER(a->registers[i]);
- rb = G_ARCH_REGISTER(b->registers[i]);
-
- result = g_arch_register_compare(ra, rb);
-
- }
-
- garoc_done:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un opérande en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *operand, GBufferLine *line)
-{
- size_t i; /* Boucle de parcours */
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "{", 1, RTT_HOOK, NULL);
-
- for (i = 0; i < operand->count; i++)
- {
- if (i > 0)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
-
- g_arch_register_print(G_ARCH_REGISTER(operand->registers[i]), line);
-
- }
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "}", 1, RTT_HOOK, NULL);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : selected = masque de bits pour les registres à intégrer. *
* *
* Description : Crée une liste vierge de registres ARM. *
@@ -322,8 +253,7 @@ GArchOperand *g_armv7_reglist_operand_new(uint16_t selected)
void g_armv7_reglist_add_register(GArmV7RegListOperand *operand, GArmV7Register *reg)
{
- operand->registers = (GArmV7Register **)realloc(operand->registers,
- ++operand->count * sizeof(GArmV7Register *));
+ operand->registers = realloc(operand->registers, ++operand->count * sizeof(GArmV7Register *));
operand->registers[operand->count - 1] = reg;
@@ -408,68 +338,135 @@ bool g_armv7_reglist_operand_has_register(const GArmV7RegListOperand *operand, c
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Compare un opérande avec un autre. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static int g_armv7_reglist_operand_compare(const GArmV7RegListOperand *a, const GArmV7RegListOperand *b, bool lock)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- size_t count; /* Quantité de registres */
- packed_buffer_t reg_pbuf; /* Tampon des données à écrire */
+ int result; /* Bilan à faire remonter */
size_t i; /* Boucle de parcours */
- off64_t pos; /* Position dans le flux */
- GArchRegister *reg; /* Registre restauré */
+ GArchRegister *ra; /* Registre de la liste A */
+ GArchRegister *rb; /* Registre de la liste B */
+ GArchOperandClass *class; /* Classe parente normalisée */
- parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class);
+ /* Création de l'objet... */
+ if (b == NULL)
+ {
+ result = 1;
+ goto done;
+ }
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
+ result = sort_unsigned_long(a->count, b->count);
- if (result)
- result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true);
+ for (i = 0; i < a->count && result == 0; i++)
+ {
+ ra = G_ARCH_REGISTER(a->registers[i]);
+ rb = G_ARCH_REGISTER(b->registers[i]);
- if (result)
+ result = g_arch_register_compare(ra, rb);
+
+ }
+
+ if (result == 0)
{
- init_packed_buffer(&reg_pbuf);
+ class = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
- for (i = 0; i < count && result; i++)
- {
- result = extract_packed_buffer(pbuf, &pos, sizeof(off64_t), true);
+ done:
- if (result)
- result = g_asm_storage_load_register_data(storage, &reg_pbuf, pos);
+ return result;
- if (result)
- {
- reg = g_arch_register_load(storage, &reg_pbuf);
- result = (reg != NULL);
- }
+}
- if (result)
- g_armv7_reglist_add_register(operand, G_ARMV7_REGISTER(reg));
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *operand, GBufferLine *line)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "{", 1, RTT_HOOK, NULL);
+
+ for (i = 0; i < operand->count; i++)
+ {
+ if (i > 0)
+ {
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
}
- exit_packed_buffer(&reg_pbuf);
+ g_arch_register_print(G_ARCH_REGISTER(operand->registers[i]), line);
}
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, "}", 1, RTT_HOOK, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
+* *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* *
+* Retour : Empreinte de l'élément représenté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static guint g_armv7_reglist_operand_hash(const GArmV7RegListOperand *operand, bool lock)
+{
+ guint result; /* Valeur à retourner */
+ operand_extra_data_t *extra; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+ size_t i; /* Boucle de parcours */
+
+ extra = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(operand));
+
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
+
+ class = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
+
+ result ^= operand->count;
+
+ for (i = 0; i < operand->count; i++)
+ result ^= g_arch_register_hash(G_ARCH_REGISTER(operand->registers[i]));
+
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
+
return result;
}
@@ -477,11 +474,11 @@ static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *operand, G
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Charge un contenu depuis une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -489,39 +486,69 @@ static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *operand, G
* *
******************************************************************************/
-static bool g_armv7_reglist_operand_serialize(const GArmV7RegListOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_armv7_reglist_operand_load(GArmV7RegListOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ size_t count; /* Quantité de registres */
size_t i; /* Boucle de parcours */
- off64_t pos; /* Position dans le flux */
- packed_buffer_t reg_pbuf; /* Tampon des données à écrire */
+ GSerializableObject *reg; /* Registre de la liste */
parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extend_packed_buffer(pbuf, &operand->count, sizeof(size_t), true);
+ result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true);
- if (result)
+ for (i = 0; i < count && result; i++)
{
- init_packed_buffer(&reg_pbuf);
+ reg = g_object_storage_unpack_object(storage, "registers", pbuf);
- for (i = 0; i < operand->count && result; i++)
- {
- result = g_arch_register_store(G_ARCH_REGISTER(operand->registers[i]), storage, &reg_pbuf);
+ result = (reg != NULL);
- if (result)
- result = g_asm_storage_store_register_data(storage, &reg_pbuf, &pos);
+ if (result)
+ g_armv7_reglist_add_register(operand, G_ARMV7_REGISTER(reg));
- if (result)
- result = extend_packed_buffer(pbuf, &pos, sizeof(off64_t), true);
+ }
- }
+ return result;
- exit_packed_buffer(&reg_pbuf);
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à remplir. *
+* *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static bool g_armv7_reglist_operand_store(GArmV7RegListOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+ size_t i; /* Boucle de parcours */
+ GSerializableObject *reg; /* Registre de la liste */
+
+ parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class);
+
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
+
+ if (result)
+ result = extend_packed_buffer(pbuf, &operand->count, sizeof(size_t), true);
+
+ for (i = 0; i < operand->count && result; i++)
+ {
+ reg = G_SERIALIZABLE_OBJECT(operand->registers[i]);
+ result = g_object_storage_pack_object(storage, "registers", reg, pbuf);
}
return result;
diff --git a/plugins/arm/v7/operands/rotation.c b/plugins/arm/v7/operands/rotation.c
index 05889f4..418e5a4 100644
--- a/plugins/arm/v7/operands/rotation.c
+++ b/plugins/arm/v7/operands/rotation.c
@@ -24,20 +24,26 @@
#include "rotation.h"
+#include <assert.h>
#include <stdio.h>
#include <string.h>
-#include <arch/operand-int.h>
+#include <core/columns.h>
#include <core/logs.h>
-#include <gtkext/gtkblockdisplay.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
/* Définition d'un opérande visant une opérande de rotation ARMv7 (instance) */
struct _GArmV7RotationOperand
{
- GArchOperand parent; /* Instance parente */
+ GArmV7Operand parent; /* Instance parente */
GArchOperand *value; /* Valeur du décalage */
@@ -47,7 +53,7 @@ struct _GArmV7RotationOperand
/* Définition d'un opérande visant une opérande de rotation ARMv7 (classe) */
struct _GArmV7RotationOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -64,8 +70,13 @@ static void g_armv7_rotation_operand_dispose(GArmV7RotationOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_rotation_operand_finalize(GArmV7RotationOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_rotation_operand_compare(const GArmV7RotationOperand *, const GArmV7RotationOperand *);
+static int g_armv7_rotation_operand_compare(const GArmV7RotationOperand *, const GArmV7RotationOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *g_armv7_rotation_operand_find_inner_operand_path(const GArmV7RotationOperand *, const GArchOperand *);
@@ -76,21 +87,21 @@ static GArchOperand *g_armv7_rotation_operand_get_inner_operand_from_path(const
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *, GBufferLine *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GArchOperand **g_armv7_rotation_operand_list_inner_instances(const GArmV7RotationOperand *, size_t *);
-
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Met à jour une liste de candidats embarqués par un candidat. */
+static void g_armv7_rotation_operand_update_inner_instances(GArmV7RotationOperand *, GArchOperand **, size_t);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_rotation_operand_unserialize(GArmV7RotationOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_rotation_operand_serialize(const GArmV7RotationOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour une opérande de rotation ARMv7. */
-G_DEFINE_TYPE(GArmV7RotationOperand, g_armv7_rotation_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7RotationOperand, g_armv7_rotation_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -123,8 +134,11 @@ static void g_armv7_rotation_operand_class_init(GArmV7RotationOperandClass *klas
operand->print = (operand_print_fc)g_armv7_rotation_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_rotation_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_rotation_operand_serialize;
+ operand->list_inner = (operand_list_inners_fc)g_armv7_rotation_operand_list_inner_instances;
+ operand->update_inner = (operand_update_inners_fc)g_armv7_rotation_operand_update_inner_instances;
+
+ operand->load = g_arch_operand_load_generic_fixed_1;
+ operand->store = g_arch_operand_store_generic_fixed;
}
@@ -162,8 +176,7 @@ static void g_armv7_rotation_operand_init(GArmV7RotationOperand *operand)
static void g_armv7_rotation_operand_dispose(GArmV7RotationOperand *operand)
{
- if (operand->value != NULL)
- g_object_unref(G_OBJECT(operand->value));
+ g_clear_object(&operand->value);
G_OBJECT_CLASS(g_armv7_rotation_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -191,8 +204,65 @@ static void g_armv7_rotation_operand_finalize(GArmV7RotationOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : - *
+* *
+* Description : Crée un réceptacle pour opérandes de rotation ARMv7. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_rotation_operand_new(GArchOperand *value)
+{
+ GArmV7RotationOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ARMV7_ROTATION_OPERAND, NULL);
+
+ result->value = value;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit la valeur utilisée pour une rotation. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_rotation_operand_get_value(const GArmV7RotationOperand *operand)
+{
+ GArchOperand *result; /* Instance à retourner */
+
+ result = operand->value;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -202,12 +272,19 @@ static void g_armv7_rotation_operand_finalize(GArmV7RotationOperand *operand)
* *
******************************************************************************/
-static int g_armv7_rotation_operand_compare(const GArmV7RotationOperand *a, const GArmV7RotationOperand *b)
+static int g_armv7_rotation_operand_compare(const GArmV7RotationOperand *a, const GArmV7RotationOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
+ GArchOperandClass *class; /* Classe parente normalisée */
result = g_arch_operand_compare(a->value, b->value);
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_rotation_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
+
return result;
}
@@ -326,96 +403,27 @@ static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *operand,
/******************************************************************************
* *
-* Paramètres : - *
-* *
-* Description : Crée un réceptacle pour opérandes de rotation ARMv7. *
-* *
-* Retour : Opérande mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_rotation_operand_new(GArchOperand *value)
-{
- GArmV7RotationOperand *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_ARMV7_ROTATION_OPERAND, NULL);
-
- result->value = value;
-
- return G_ARCH_OPERAND(result);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit la valeur utilisée pour une rotation. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_rotation_operand_get_value(const GArmV7RotationOperand *operand)
-{
- GArchOperand *result; /* Instance à retourner */
-
- result = operand->value;
-
- g_object_ref(G_OBJECT(result));
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Fournit une liste de candidats embarqués par un candidat. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Liste de candidats internes ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_rotation_operand_unserialize(GArmV7RotationOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static GArchOperand **g_armv7_rotation_operand_list_inner_instances(const GArmV7RotationOperand *operand, size_t *count)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- GArchOperand *value; /* Valeur à intégrer */
+ GArchOperand **result; /* Instances à retourner */
- parent = G_ARCH_OPERAND_CLASS(g_armv7_rotation_operand_parent_class);
+ *count = 1;
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- {
- value = g_arch_operand_load(storage, format, pbuf);
+ result = malloc(*count * sizeof(GArchOperand *));
- if (value == NULL)
- result = false;
-
- else
- operand->value = value;
-
- }
+ result[0] = operand->value;
+ g_object_ref(G_OBJECT(result[0]));
return result;
@@ -424,30 +432,25 @@ static bool g_armv7_rotation_operand_unserialize(GArmV7RotationOperand *operand,
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* instances = liste de candidats internes devenus singletons. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Met à jour une liste de candidats embarqués par un candidat. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_rotation_operand_serialize(const GArmV7RotationOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static void g_armv7_rotation_operand_update_inner_instances(GArmV7RotationOperand *operand, GArchOperand **instances, size_t count)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_rotation_operand_parent_class);
+ assert(count == 1);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ g_clear_object(&operand->value);
- if (result)
- result = g_arch_operand_store(operand->value, storage, pbuf);
-
- return result;
+ operand->value = instances[0];
+ g_object_ref(G_OBJECT(instances[0]));
}
diff --git a/plugins/arm/v7/operands/shift.c b/plugins/arm/v7/operands/shift.c
index 852e677..ee18cf0 100644
--- a/plugins/arm/v7/operands/shift.c
+++ b/plugins/arm/v7/operands/shift.c
@@ -24,22 +24,37 @@
#include "shift.h"
+#include <assert.h>
#include <stdio.h>
#include <string.h>
-#include <arch/operand-int.h>
#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _a7shiftop_extra_data_t
+{
+ operand_extra_data_t parent; /* A laisser en premier */
+
+ SRType shift_type; /* Type de décalage */
+
+} a7shiftop_extra_data_t;
+
/* Définition d'un opérande visant une opérande de décalage ARMv7 (instance) */
struct _GArmV7ShiftOperand
{
- GArchOperand parent; /* Instance parente */
+ GArmV7Operand parent; /* Instance parente */
- SRType shift_type; /* Type de décalage */
GArchOperand *shift_value; /* Valeur du décalage */
};
@@ -48,11 +63,26 @@ struct _GArmV7ShiftOperand
/* Définition d'un opérande visant une opérande de décalage ARMv7 (classe) */
struct _GArmV7ShiftOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
+/**
+ * Accès aux informations éventuellement déportées.
+ */
+
+#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+
+# define GET_ARMV7_SHIFT_OP_EXTRA(op) ((a7shiftop_extra_data_t *)&((GArchOperand *)op)->extra)
+
+#else
+
+# define GET_ARMV7_SHIFT_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7shiftop_extra_data_t)
+
+#endif
+
+
/* Initialise la classe des opérandes de décalage ARMv7. */
static void g_armv7_shift_operand_class_init(GArmV7ShiftOperandClass *);
@@ -65,8 +95,13 @@ static void g_armv7_shift_operand_dispose(GArmV7ShiftOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_shift_operand_finalize(GArmV7ShiftOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_shift_operand_compare(const GArmV7ShiftOperand *, const GArmV7ShiftOperand *);
+static int g_armv7_shift_operand_compare(const GArmV7ShiftOperand *, const GArmV7ShiftOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *g_armv7_shift_operand_find_inner_operand_path(const GArmV7ShiftOperand *, const GArchOperand *);
@@ -77,21 +112,30 @@ static GArchOperand *g_armv7_shift_operand_get_inner_operand_from_path(const GAr
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *, GBufferLine *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GArchOperand **g_armv7_shift_operand_list_inner_instances(const GArmV7ShiftOperand *, size_t *);
+/* Met à jour une liste de candidats embarqués par un candidat. */
+static void g_armv7_shift_operand_update_inner_instances(GArmV7ShiftOperand *, GArchOperand **, size_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_shift_operand_hash(const GArmV7ShiftOperand *, bool);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_shift_operand_load(GArmV7ShiftOperand *, GObjectStorage *, packed_buffer_t *);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_shift_operand_unserialize(GArmV7ShiftOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_shift_operand_store(GArmV7ShiftOperand *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_shift_operand_serialize(const GArmV7ShiftOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
+
/* Indique le type défini par la GLib pour une opérande de décalage ARMv7. */
-G_DEFINE_TYPE(GArmV7ShiftOperand, g_armv7_shift_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7ShiftOperand, g_armv7_shift_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -124,8 +168,12 @@ static void g_armv7_shift_operand_class_init(GArmV7ShiftOperandClass *klass)
operand->print = (operand_print_fc)g_armv7_shift_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_shift_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_shift_operand_serialize;
+ operand->list_inner = (operand_list_inners_fc)g_armv7_shift_operand_list_inner_instances;
+ operand->update_inner = (operand_update_inners_fc)g_armv7_shift_operand_update_inner_instances;
+ operand->hash = (operand_hash_fc)g_armv7_shift_operand_hash;
+
+ operand->load = (load_operand_fc)g_armv7_shift_operand_load;
+ operand->store = (store_operand_fc)g_armv7_shift_operand_store;
}
@@ -163,8 +211,7 @@ static void g_armv7_shift_operand_init(GArmV7ShiftOperand *operand)
static void g_armv7_shift_operand_dispose(GArmV7ShiftOperand *operand)
{
- if (operand->shift_value != NULL)
- g_object_unref(G_OBJECT(operand->shift_value));
+ g_clear_object(&operand->shift_value);
G_OBJECT_CLASS(g_armv7_shift_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -192,8 +239,100 @@ static void g_armv7_shift_operand_finalize(GArmV7ShiftOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : - *
+* *
+* Description : Crée un réceptacle pour opérande de décalage ARMv7. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_shift_operand_new(SRType type, GArchOperand *value)
+{
+ GArmV7ShiftOperand *result; /* Structure à retourner */
+ a7shiftop_extra_data_t *extra; /* Données insérées à modifier */
+
+ result = g_object_new(G_TYPE_ARMV7_SHIFT_OPERAND, NULL);
+
+ extra = GET_ARMV7_SHIFT_OP_EXTRA(result);
+
+ extra->shift_type = type;
+
+ result->shift_value = value;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Indique la forme de décalage représenté. *
+* *
+* Retour : Type de décalage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+SRType g_armv7_shift_operand_get_shift_type(const GArmV7ShiftOperand *operand)
+{
+ SRType result; /* Type à retourner */
+ a7shiftop_extra_data_t *extra; /* Données insérées à consulter*/
+
+ extra = GET_ARMV7_SHIFT_OP_EXTRA(operand);
+
+ LOCK_GOBJECT_EXTRA(extra);
+
+ result = extra->shift_type;
+
+ UNLOCK_GOBJECT_EXTRA(extra);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit la valeur utilisée pour un décalage. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_shift_operand_get_shift_value(const GArmV7ShiftOperand *operand)
+{
+ GArchOperand *result; /* Instance à retourner */
+
+ result = operand->shift_value;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -203,16 +342,38 @@ static void g_armv7_shift_operand_finalize(GArmV7ShiftOperand *operand)
* *
******************************************************************************/
-static int g_armv7_shift_operand_compare(const GArmV7ShiftOperand *a, const GArmV7ShiftOperand *b)
+static int g_armv7_shift_operand_compare(const GArmV7ShiftOperand *a, const GArmV7ShiftOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
+ a7shiftop_extra_data_t *ea; /* Données insérées à consulter*/
+ a7shiftop_extra_data_t *eb; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+
+ ea = GET_ARMV7_SHIFT_OP_EXTRA(a);
+ eb = GET_ARMV7_SHIFT_OP_EXTRA(b);
+
+ if (lock)
+ {
+ LOCK_GOBJECT_EXTRA(ea);
+ LOCK_GOBJECT_EXTRA(eb);
+ }
+
+ result = sort_unsigned_long(ea->shift_type, eb->shift_type);
- result = sort_unsigned_long(a->shift_type, b->shift_type);
- if (result != 0) goto gasoc_done;
+ if (result == 0)
+ result = g_arch_operand_compare(a->shift_value, b->shift_value);
- result = g_arch_operand_compare(a->shift_value, b->shift_value);
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
- gasoc_done:
+ if (lock)
+ {
+ UNLOCK_GOBJECT_EXTRA(eb);
+ UNLOCK_GOBJECT_EXTRA(ea);
+ }
return result;
@@ -299,7 +460,11 @@ static GArchOperand *g_armv7_shift_operand_get_inner_operand_from_path(const GAr
static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *operand, GBufferLine *line)
{
- switch (operand->shift_type)
+ SRType shift_type; /* Type porté par l'opérande */
+
+ shift_type = g_armv7_shift_operand_get_shift_type(operand);
+
+ switch (shift_type)
{
case SRType_LSL:
g_buffer_line_append_text(line, DLC_ASSEMBLY, "lsl", 3, RTT_KEY_WORD, NULL);
@@ -327,88 +492,106 @@ static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *operand, GBuff
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Crée un réceptacle pour opérande de décalage ARMv7. *
+* Description : Fournit une liste de candidats embarqués par un candidat. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Liste de candidats internes ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_shift_operand_new(SRType type, GArchOperand *value)
+static GArchOperand **g_armv7_shift_operand_list_inner_instances(const GArmV7ShiftOperand *operand, size_t *count)
{
- GArmV7ShiftOperand *result; /* Structure à retourner */
+ GArchOperand **result; /* Instances à retourner */
- result = g_object_new(G_TYPE_ARMV7_SHIFT_OPERAND, NULL);
+ *count = 1;
- result->shift_type = type;
- result->shift_value = value;
+ result = malloc(*count * sizeof(GArchOperand *));
- return G_ARCH_OPERAND(result);
+ result[0] = operand->shift_value;
+ g_object_ref(G_OBJECT(result[0]));
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : operand = opérande à consulter. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* instances = liste de candidats internes devenus singletons. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Indique la forme de décalage représenté. *
+* Description : Met à jour une liste de candidats embarqués par un candidat. *
* *
-* Retour : Type de décalage. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-SRType g_armv7_shift_operand_get_shift_type(const GArmV7ShiftOperand *operand)
+static void g_armv7_shift_operand_update_inner_instances(GArmV7ShiftOperand *operand, GArchOperand **instances, size_t count)
{
- return operand->shift_type;
+ assert(count == 1);
+
+ g_clear_object(&operand->shift_value);
+
+ operand->shift_value = instances[0];
+ g_object_ref(G_OBJECT(instances[0]));
}
/******************************************************************************
* *
-* Paramètres : operand = opérande à consulter. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Founit la valeur utilisée pour un décalage. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Opérande en place. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_shift_operand_get_shift_value(const GArmV7ShiftOperand *operand)
+static guint g_armv7_shift_operand_hash(const GArmV7ShiftOperand *operand, bool lock)
{
- GArchOperand *result; /* Instance à retourner */
+ guint result; /* Valeur à retourner */
+ a7shiftop_extra_data_t *extra; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+ a7shiftop_extra_data_t *op_extra; /* Données internes à manipuler*/
- result = operand->shift_value;
+ extra = GET_ARMV7_SHIFT_OP_EXTRA(G_ARMV7_SHIFT_OPERAND(operand));
- g_object_ref(G_OBJECT(result));
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- return result;
+ class = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
-}
+ op_extra = GET_ARMV7_SHIFT_OP_EXTRA(operand);
+ result ^= op_extra->shift_type;
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
+ return result;
+
+}
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Charge un contenu depuis une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -416,31 +599,31 @@ GArchOperand *g_armv7_shift_operand_get_shift_value(const GArmV7ShiftOperand *op
* *
******************************************************************************/
-static bool g_armv7_shift_operand_unserialize(GArmV7ShiftOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_armv7_shift_operand_load(GArmV7ShiftOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
- GArchOperand *value; /* Valeur à intégrer */
+ a7shiftop_extra_data_t *extra; /* Données insérées à modifier */
+ uleb128_t value; /* Valeur ULEB128 à charger */
parent = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class);
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- result = extract_packed_buffer(pbuf, &operand->shift_type, sizeof(SRType), true);
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
{
- value = g_arch_operand_load(storage, format, pbuf);
+ extra = GET_ARMV7_SHIFT_OP_EXTRA(operand);
- if (value == NULL)
- result = false;
+ result = unpack_uleb128(&value, pbuf);
- else
- operand->shift_value = value;
+ if (result)
+ extra->shift_type = value;
}
+ if (result)
+ result = _g_arch_operand_load_inner_instances(G_ARCH_OPERAND(operand), storage, pbuf, 1);
+
return result;
}
@@ -448,11 +631,11 @@ static bool g_armv7_shift_operand_unserialize(GArmV7ShiftOperand *operand, GAsmS
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -460,20 +643,26 @@ static bool g_armv7_shift_operand_unserialize(GArmV7ShiftOperand *operand, GAsmS
* *
******************************************************************************/
-static bool g_armv7_shift_operand_serialize(const GArmV7ShiftOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_armv7_shift_operand_store(GArmV7ShiftOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ a7shiftop_extra_data_t *extra; /* Données insérées à modifier */
parent = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extend_packed_buffer(pbuf, &operand->shift_type, sizeof(SRType), true);
+ {
+ extra = GET_ARMV7_SHIFT_OP_EXTRA(operand);
+
+ result = pack_uleb128((uleb128_t []){ extra->shift_type }, pbuf);
+
+ }
if (result)
- result = g_arch_operand_store(operand->shift_value, storage, pbuf);
+ result = _g_arch_operand_store_inner_instances(G_ARCH_OPERAND(operand), storage, pbuf, true);
return result;
diff --git a/plugins/arm/v7/registers/Makefile.am b/plugins/arm/v7/registers/Makefile.am
index 94edf09..5f731f9 100644
--- a/plugins/arm/v7/registers/Makefile.am
+++ b/plugins/arm/v7/registers/Makefile.am
@@ -1,21 +1,16 @@
noinst_LTLIBRARIES = libarmv7registers.la
-libarmv7registers_la_SOURCES = \
- banked.h banked.c \
- basic.h basic.c \
- coproc.h coproc.c \
- simd.h simd.c \
+libarmv7registers_la_SOURCES = \
+ banked.h banked.c \
+ basic.h basic.c \
+ coproc.h coproc.c \
+ simd.h simd.c \
special.h special.c
-libarmv7registers_la_LIBADD =
+libarmv7registers_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libarmv7registers_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/arm/v7/registers/banked.c b/plugins/arm/v7/registers/banked.c
index daeae71..6e9fbf3 100644
--- a/plugins/arm/v7/registers/banked.c
+++ b/plugins/arm/v7/registers/banked.c
@@ -27,7 +27,7 @@
#include <stdio.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
#include "../register-int.h"
@@ -78,14 +78,6 @@ static GArchRegister *_g_armv7_banked_register_new(BankedRegisterTarget);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
-
-
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_armv7_banked_register_unserialize(GArmV7BankedRegister *, GAsmStorage *, packed_buffer_t *);
-
-
-
/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */
@@ -133,7 +125,6 @@ static void g_armv7_banked_register_class_init(GArmV7BankedRegisterClass *klass)
object_class->finalize = (GObjectFinalizeFunc)g_armv7_banked_register_finalize;
reg_class->print = (reg_print_fc)g_armv7_banked_register_print;
- reg_class->unserialize = (reg_unserialize_fc)g_armv7_banked_register_unserialize;
}
@@ -567,63 +558,6 @@ BankedRegisterTarget g_armv7_banked_register_get_target(const GArmV7BankedRegist
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un registre depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GArchRegister *g_armv7_banked_register_unserialize(GArmV7BankedRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
-{
- GArchRegister *result; /* Instance à retourner */
- uint8_t index; /* Indice du registre */
- bool status; /* Bilan d'une extraction */
- GArchRegisterClass *parent; /* Classe parente à consulter */
-
- status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false);
-
- if (status)
- {
- result = get_armv7_banked_register(index);
-
- if (result == NULL)
- g_object_unref(G_OBJECT(reg));
-
- }
-
- else
- {
- g_object_unref(G_OBJECT(reg));
- result = NULL;
- }
-
- if (result != NULL)
- {
- parent = G_ARCH_REGISTER_CLASS(g_armv7_banked_register_parent_class);
-
- result = parent->unserialize(result, storage, pbuf);
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* GESTION SOUS FORME DE SINGLETONS */
/* ---------------------------------------------------------------------------------- */
diff --git a/plugins/arm/v7/registers/basic.c b/plugins/arm/v7/registers/basic.c
index d92f74e..358135b 100644
--- a/plugins/arm/v7/registers/basic.c
+++ b/plugins/arm/v7/registers/basic.c
@@ -27,7 +27,7 @@
#include <stdio.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
#include "../register-int.h"
@@ -75,14 +75,6 @@ static GArchRegister *_g_armv7_basic_register_new(uint8_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
-
-
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_armv7_basic_register_unserialize(GArmV7BasicRegister *, GAsmStorage *, packed_buffer_t *);
-
-
-
/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */
@@ -130,7 +122,6 @@ static void g_armv7_basic_register_class_init(GArmV7BasicRegisterClass *klass)
object_class->finalize = (GObjectFinalizeFunc)g_armv7_basic_register_finalize;
reg_class->print = (reg_print_fc)g_armv7_basic_register_print;
- reg_class->unserialize = (reg_unserialize_fc)g_armv7_basic_register_unserialize;
}
@@ -302,63 +293,6 @@ GArchRegister *g_armv7_basic_register_new(uint8_t index)
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un registre depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GArchRegister *g_armv7_basic_register_unserialize(GArmV7BasicRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
-{
- GArchRegister *result; /* Instance à retourner */
- uint8_t index; /* Indice du registre */
- bool status; /* Bilan d'une extraction */
- GArchRegisterClass *parent; /* Classe parente à consulter */
-
- status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false);
-
- if (status)
- {
- result = get_armv7_basic_register(index);
-
- if (result == NULL)
- g_object_unref(G_OBJECT(reg));
-
- }
-
- else
- {
- g_object_unref(G_OBJECT(reg));
- result = NULL;
- }
-
- if (result != NULL)
- {
- parent = G_ARCH_REGISTER_CLASS(g_armv7_basic_register_parent_class);
-
- result = parent->unserialize(result, storage, pbuf);
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* GESTION SOUS FORME DE SINGLETONS */
/* ---------------------------------------------------------------------------------- */
diff --git a/plugins/arm/v7/registers/coproc.c b/plugins/arm/v7/registers/coproc.c
index acfbb81..5c256a7 100644
--- a/plugins/arm/v7/registers/coproc.c
+++ b/plugins/arm/v7/registers/coproc.c
@@ -27,7 +27,7 @@
#include <stdio.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
#include "../register-int.h"
@@ -76,14 +76,6 @@ static GArchRegister *_g_armv7_cp_register_new(uint8_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
-
-
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_armv7_cp_register_unserialize(GArmV7CpRegister *, GAsmStorage *, packed_buffer_t *);
-
-
-
/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */
@@ -131,7 +123,6 @@ static void g_armv7_cp_register_class_init(GArmV7CpRegisterClass *klass)
object_class->finalize = (GObjectFinalizeFunc)g_armv7_cp_register_finalize;
reg_class->print = (reg_print_fc)g_armv7_cp_register_print;
- reg_class->unserialize = (reg_unserialize_fc)g_armv7_cp_register_unserialize;
}
@@ -282,63 +273,6 @@ GArchRegister *g_armv7_cp_register_new(uint8_t index)
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un registre depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GArchRegister *g_armv7_cp_register_unserialize(GArmV7CpRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
-{
- GArchRegister *result; /* Instance à retourner */
- uint8_t index; /* Indice du registre */
- bool status; /* Bilan d'une extraction */
- GArchRegisterClass *parent; /* Classe parente à consulter */
-
- status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false);
-
- if (status)
- {
- result = get_armv7_cp_register(index);
-
- if (result == NULL)
- g_object_unref(G_OBJECT(reg));
-
- }
-
- else
- {
- g_object_unref(G_OBJECT(reg));
- result = NULL;
- }
-
- if (result != NULL)
- {
- parent = G_ARCH_REGISTER_CLASS(g_armv7_cp_register_parent_class);
-
- result = parent->unserialize(result, storage, pbuf);
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* GESTION SOUS FORME DE SINGLETONS */
/* ---------------------------------------------------------------------------------- */
diff --git a/plugins/arm/v7/registers/simd.c b/plugins/arm/v7/registers/simd.c
index eedd7c8..8c8c653 100644
--- a/plugins/arm/v7/registers/simd.c
+++ b/plugins/arm/v7/registers/simd.c
@@ -28,7 +28,7 @@
#include <stdio.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
#include "../register-int.h"
@@ -70,22 +70,21 @@ static void g_armv7_simd_register_dispose(GArmV7SIMDRegister *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_simd_register_finalize(GArmV7SIMDRegister *);
-/* Traduit un registre en version humainement lisible. */
-static void g_armv7_simd_register_print(const GArmV7SIMDRegister *, GBufferLine *);
-
/* Crée une réprésentation de registre SIMD ARMv7. */
static GArchRegister *_g_armv7_simd_register_new(SIMDRegisterMapping, uint8_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Traduit un registre en version humainement lisible. */
+static void g_armv7_simd_register_print(const GArmV7SIMDRegister *, GBufferLine *);
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_armv7_simd_register_unserialize(GArmV7SIMDRegister *, GAsmStorage *, packed_buffer_t *);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_simd_register_load(GArmV7SIMDRegister *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un registre dans une mémoire tampon. */
-static bool g_armv7_simd_register_serialize(const GArmV7SIMDRegister *, GAsmStorage *, packed_buffer_t *);
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_simd_register_store(GArmV7SIMDRegister *, GObjectStorage *, packed_buffer_t *);
@@ -126,20 +125,20 @@ G_DEFINE_TYPE(GArmV7SIMDRegister, g_armv7_simd_register, G_TYPE_ARMV7_REGISTER);
static void g_armv7_simd_register_class_init(GArmV7SIMDRegisterClass *klass)
{
- GObjectClass *object_class; /* Autre version de la classe */
- GArchRegisterClass *reg_class; /* Classe de haut niveau */
+ GObjectClass *object; /* Autre version de la classe */
+ GArchRegisterClass *reg; /* Classe de haut niveau */
- object_class = G_OBJECT_CLASS(klass);
+ object = G_OBJECT_CLASS(klass);
- object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_simd_register_dispose;
- object_class->finalize = (GObjectFinalizeFunc)g_armv7_simd_register_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_simd_register_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_armv7_simd_register_finalize;
- reg_class = G_ARCH_REGISTER_CLASS(klass);
+ reg = G_ARCH_REGISTER_CLASS(klass);
- reg_class->print = (reg_print_fc)g_armv7_simd_register_print;
- reg_class->unserialize = (reg_unserialize_fc)g_armv7_simd_register_unserialize;
- reg_class->serialize = (reg_serialize_fc)g_armv7_simd_register_serialize;
+ reg->print = (reg_print_fc)g_armv7_simd_register_print;
+ reg->load = (load_register_fc)g_armv7_simd_register_load;
+ reg->store = (store_register_fc)g_armv7_simd_register_store;
}
@@ -202,50 +201,6 @@ static void g_armv7_simd_register_finalize(GArmV7SIMDRegister *reg)
/******************************************************************************
* *
-* Paramètres : reg = registre à transcrire. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un registre en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_armv7_simd_register_print(const GArmV7SIMDRegister *reg, GBufferLine *line)
-{
- char key[MAX_REGNAME_LEN]; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
-
- switch (reg->mapping)
- {
- case SRM_SINGLE_WORD:
- klen = snprintf(key, MAX_REGNAME_LEN, "s%hhu", G_ARM_REGISTER(reg)->index);
- break;
-
- case SRM_DOUBLE_WORD:
- klen = snprintf(key, MAX_REGNAME_LEN, "d%hhu", G_ARM_REGISTER(reg)->index);
- break;
-
- case SRM_QUAD_WORD:
- klen = snprintf(key, MAX_REGNAME_LEN, "q%hhu", G_ARM_REGISTER(reg)->index);
- break;
-
- default:
- assert(false);
- klen = snprintf(key, MAX_REGNAME_LEN, "x??");
- break;
-
- }
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : mapping = type de registre demandé. *
* index = indice du registre correspondant. *
* *
@@ -328,57 +283,84 @@ GArchRegister *g_armv7_simd_register_new(SIMDRegisterMapping mapping, uint8_t in
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : reg = registre à transcrire. *
+* line = ligne tampon où imprimer l'opérande donné. *
* *
-* Description : Charge un registre depuis une mémoire tampon. *
+* Description : Traduit un registre en version humainement lisible. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GArchRegister *g_armv7_simd_register_unserialize(GArmV7SIMDRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
+static void g_armv7_simd_register_print(const GArmV7SIMDRegister *reg, GBufferLine *line)
{
- GArchRegister *result; /* Instance à retourner */
- SIMDRegisterMapping mapping; /* Type de registre */
- bool status; /* Bilan d'une extraction */
- uint8_t index; /* Indice du registre */
- GArchRegisterClass *parent; /* Classe parente à consulter */
+ char key[MAX_REGNAME_LEN]; /* Mot clef principal */
+ size_t klen; /* Taille de ce mot clef */
- status = extract_packed_buffer(pbuf, &mapping, sizeof(SIMDRegisterMapping), true);
+ switch (reg->mapping)
+ {
+ case SRM_SINGLE_WORD:
+ klen = snprintf(key, MAX_REGNAME_LEN, "s%hhu", G_ARM_REGISTER(reg)->index);
+ break;
- if (status)
- status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false);
+ case SRM_DOUBLE_WORD:
+ klen = snprintf(key, MAX_REGNAME_LEN, "d%hhu", G_ARM_REGISTER(reg)->index);
+ break;
- if (status)
- {
- result = get_armv7_simd_register(mapping, index);
+ case SRM_QUAD_WORD:
+ klen = snprintf(key, MAX_REGNAME_LEN, "q%hhu", G_ARM_REGISTER(reg)->index);
+ break;
- if (result == NULL)
- g_object_unref(G_OBJECT(reg));
+ default:
+ assert(false);
+ klen = snprintf(key, MAX_REGNAME_LEN, "x??");
+ break;
}
- else
- {
- g_object_unref(G_OBJECT(reg));
- result = NULL;
- }
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
- if (result != NULL)
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reg = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
+* *
+* Description : Charge un contenu depuis une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_armv7_simd_register_load(GArmV7SIMDRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchRegisterClass *parent; /* Classe parente à consulter */
+ uleb128_t value; /* Valeur à charger */
+
+ parent = G_ARCH_REGISTER_CLASS(g_armv7_simd_register_parent_class);
+
+ result = parent->load(G_ARCH_REGISTER(reg), storage, pbuf);
+
+ if (result)
{
- parent = G_ARCH_REGISTER_CLASS(g_armv7_simd_register_parent_class);
+ result = unpack_uleb128(&value, pbuf);
- result = parent->unserialize(G_ARCH_REGISTER(reg), storage, pbuf);
+ if (result)
+ reg->mapping = value;
}
@@ -389,11 +371,11 @@ static GArchRegister *g_armv7_simd_register_unserialize(GArmV7SIMDRegister *reg,
/******************************************************************************
* *
-* Paramètres : reg = registre d'architecture à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : reg = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un registre dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -401,20 +383,17 @@ static GArchRegister *g_armv7_simd_register_unserialize(GArmV7SIMDRegister *reg,
* *
******************************************************************************/
-static bool g_armv7_simd_register_serialize(const GArmV7SIMDRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_armv7_simd_register_store(GArmV7SIMDRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchRegisterClass *parent; /* Classe parente à consulter */
- result = extend_packed_buffer(pbuf, &reg->mapping, sizeof(SIMDRegisterMapping), true);
-
- if (result)
- {
- parent = G_ARCH_REGISTER_CLASS(g_armv7_simd_register_parent_class);
+ parent = G_ARCH_REGISTER_CLASS(g_armv7_simd_register_parent_class);
- result = parent->serialize(G_ARCH_REGISTER(reg), storage, pbuf);
+ result = parent->store(G_ARCH_REGISTER(reg), storage, pbuf);
- }
+ if (result)
+ result = pack_uleb128((uleb128_t []){ reg->mapping }, pbuf);
return result;
diff --git a/plugins/arm/v7/registers/special.c b/plugins/arm/v7/registers/special.c
index ff46a1e..1fc9eb5 100644
--- a/plugins/arm/v7/registers/special.c
+++ b/plugins/arm/v7/registers/special.c
@@ -27,7 +27,7 @@
#include <stdio.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
#include "../register-int.h"
@@ -75,14 +75,6 @@ static GArchRegister *_g_armv7_special_register_new(SpecRegTarget);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
-
-
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_armv7_special_register_unserialize(GArmV7SpecialRegister *, GAsmStorage *, packed_buffer_t *);
-
-
-
/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */
@@ -130,7 +122,6 @@ static void g_armv7_special_register_class_init(GArmV7SpecialRegisterClass *klas
object_class->finalize = (GObjectFinalizeFunc)g_armv7_special_register_finalize;
reg_class->print = (reg_print_fc)g_armv7_special_register_print;
- reg_class->unserialize = (reg_unserialize_fc)g_armv7_special_register_unserialize;
}
@@ -326,63 +317,6 @@ GArchRegister *g_armv7_special_register_new(SpecRegTarget target)
/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un registre depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GArchRegister *g_armv7_special_register_unserialize(GArmV7SpecialRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
-{
- GArchRegister *result; /* Instance à retourner */
- uint8_t index; /* Indice du registre */
- bool status; /* Bilan d'une extraction */
- GArchRegisterClass *parent; /* Classe parente à consulter */
-
- status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false);
-
- if (status)
- {
- result = get_armv7_special_register(index);
-
- if (result == NULL)
- g_object_unref(G_OBJECT(reg));
-
- }
-
- else
- {
- g_object_unref(G_OBJECT(reg));
- result = NULL;
- }
-
- if (result != NULL)
- {
- parent = G_ARCH_REGISTER_CLASS(g_armv7_special_register_parent_class);
-
- result = parent->unserialize(result, storage, pbuf);
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* GESTION SOUS FORME DE SINGLETONS */
/* ---------------------------------------------------------------------------------- */
diff --git a/plugins/bhash/Makefile.am b/plugins/bhash/Makefile.am
index 45c5ee0..31daeb1 100644
--- a/plugins/bhash/Makefile.am
+++ b/plugins/bhash/Makefile.am
@@ -45,9 +45,11 @@ libbhash_la_SOURCES = \
tlsh.h tlsh.c \
rich.h rich.c
-libbhash_la_LIBADD = \
+libbhash_la_LIBADD = \
$(PYTHON3_LIBADD)
+libbhash_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libbhash_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -60,8 +62,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libbhash_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/bhash/core.c b/plugins/bhash/core.c
index 91a0bf2..eb05893 100644
--- a/plugins/bhash/core.c
+++ b/plugins/bhash/core.c
@@ -24,16 +24,15 @@
#include "core.h"
-#include <config.h>
#include <plugins/self.h>
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS_
+#ifdef INCLUDE_PYTHON3_BINDINGS_
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -63,7 +62,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
result = add_bhash_module_to_python_module();
#else
result = true;
diff --git a/plugins/bhash/python/Makefile.am b/plugins/bhash/python/Makefile.am
index 822a716..6dd127c 100644
--- a/plugins/bhash/python/Makefile.am
+++ b/plugins/bhash/python/Makefile.am
@@ -1,21 +1,16 @@
noinst_LTLIBRARIES = libbhashpython.la
-libbhashpython_la_SOURCES = \
- imphash.h imphash.c \
- module.h module.c \
- tlsh.h tlsh.c \
+libbhashpython_la_SOURCES = \
+ imphash.h imphash.c \
+ module.h module.c \
+ tlsh.h tlsh.c \
rich.h rich.c
-libbhashpython_la_LDFLAGS =
+libbhashpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libbhashpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/bootimg/Makefile.am b/plugins/bootimg/Makefile.am
index ada1e4e..623c555 100644
--- a/plugins/bootimg/Makefile.am
+++ b/plugins/bootimg/Makefile.am
@@ -35,15 +35,17 @@ PYTHON3_SUBDIRS = python
endif
-libbootimg_la_SOURCES = \
- core.h core.c \
- bootimg-def.h \
- format-int.h format-int.c \
+libbootimg_la_SOURCES = \
+ core.h core.c \
+ bootimg-def.h \
+ format-int.h format-int.c \
format.h format.c
-libbootimg_la_LIBADD = \
+libbootimg_la_LIBADD = \
$(PYTHON3_LIBADD)
+libbootimg_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libbootimg_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -55,8 +57,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libbootimg_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/bootimg/core.c b/plugins/bootimg/core.c
index 9c4bc45..25b21db 100644
--- a/plugins/bootimg/core.c
+++ b/plugins/bootimg/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/global.h>
#include <plugins/self.h>
#include "format.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
result = add_format_bootimg_module_to_python_module();
#else
result = true;
diff --git a/plugins/bootimg/format-int.h b/plugins/bootimg/format-int.h
index 560841d..9662856 100644
--- a/plugins/bootimg/format-int.h
+++ b/plugins/bootimg/format-int.h
@@ -37,8 +37,6 @@ struct _GBootImgFormat
{
GKnownFormat parent; /* A laisser en premier */
- GBinContent *content; /* Contenu binaire à étudier */
-
boot_img_hdr header; /* Entête du format */
};
diff --git a/plugins/bootimg/python/Makefile.am b/plugins/bootimg/python/Makefile.am
index 1f11581..d39a521 100644
--- a/plugins/bootimg/python/Makefile.am
+++ b/plugins/bootimg/python/Makefile.am
@@ -1,20 +1,15 @@
noinst_LTLIBRARIES = libbootimgpython.la
-libbootimgpython_la_SOURCES = \
- format.h format.c \
- module.h module.c \
+libbootimgpython_la_SOURCES = \
+ format.h format.c \
+ module.h module.c \
translate.h translate.c
-libbootimgpython_la_LDFLAGS =
+libbootimgpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libbootimgpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/bootimg/python/format.c b/plugins/bootimg/python/format.c
index d5e32d3..273daee 100644
--- a/plugins/bootimg/python/format.c
+++ b/plugins/bootimg/python/format.c
@@ -95,7 +95,7 @@ static PyObject *py_bootimg_format_new(PyTypeObject *type, PyObject *args, PyObj
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -395,7 +395,10 @@ bool register_python_bootimg_format(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BOOTIMG_FORMAT, type, get_python_known_format_type()))
+ if (!ensure_python_known_format_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_BOOTIMG_FORMAT, type))
return false;
return true;
diff --git a/plugins/dalvik/Makefile.am b/plugins/dalvik/Makefile.am
index 644c38a..62ee8a6 100644
--- a/plugins/dalvik/Makefile.am
+++ b/plugins/dalvik/Makefile.am
@@ -39,26 +39,28 @@ PYTHON3_SUBDIRS = python
endif
-libdalvik_la_SOURCES = \
- context.h context.c \
- core.h core.c \
- fetch.h fetch.c \
- helpers.h \
- instruction-int.h \
- instruction.h instruction.c \
- link.h link.c \
- operand.h operand.c \
- post.h post.c \
- processor-int.h \
- processor.h processor.c \
+libdalvik_la_SOURCES = \
+ context.h context.c \
+ core.h core.c \
+ fetch.h fetch.c \
+ helpers.h \
+ instruction-int.h \
+ instruction.h instruction.c \
+ link.h link.c \
+ operand.h operand.c \
+ post.h post.c \
+ processor-int.h \
+ processor.h processor.c \
register.h register.c
-libdalvik_la_LIBADD = \
- operands/libdalvikoperands.la \
- pseudo/libdalvikpseudo.la \
- $(PYTHON3_LIBADD) \
+libdalvik_la_LIBADD = \
+ operands/libdalvikoperands.la \
+ pseudo/libdalvikpseudo.la \
+ $(PYTHON3_LIBADD) \
v35/libdalvik35.la
+libdalvik_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libdalvik_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -71,9 +73,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvik_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
SUBDIRS = operands pseudo $(PYTHON3_SUBDIRS) v35
diff --git a/plugins/dalvik/context.c b/plugins/dalvik/context.c
index b08678c..9cf878b 100644
--- a/plugins/dalvik/context.c
+++ b/plugins/dalvik/context.c
@@ -373,7 +373,7 @@ bool g_dalvik_context_register_array_data_padding(GDalvikContext *ctx, const vmp
* *
******************************************************************************/
-GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos)
+GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, GBinContent *content, vmpa2t *pos)
{
GArchInstruction *result; /* Instruction à retourner */
raw_data_area *found; /* Zone de couverture trouvée */
@@ -390,7 +390,7 @@ GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinC
if (found)
{
- restricted = g_restricted_content_new_ro(content, &found->range);
+ restricted = g_restricted_content_new(content, &found->range);
length = get_mrange_length(&found->range);
count = length / found->item_len;
diff --git a/plugins/dalvik/context.h b/plugins/dalvik/context.h
index bfa2757..f09cfa6 100644
--- a/plugins/dalvik/context.h
+++ b/plugins/dalvik/context.h
@@ -67,7 +67,7 @@ bool g_dalvik_context_register_array_data(GDalvikContext *, const vmpa2t *, uint
bool g_dalvik_context_register_array_data_padding(GDalvikContext *, const vmpa2t *);
/* Place une donnée en tant qu'instruction si besoin est. */
-GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *, const GBinContent *, vmpa2t *);
+GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *, GBinContent *, vmpa2t *);
diff --git a/plugins/dalvik/core.c b/plugins/dalvik/core.c
index 2294ed4..8344825 100644
--- a/plugins/dalvik/core.c
+++ b/plugins/dalvik/core.c
@@ -24,7 +24,6 @@
#include "core.h"
-#include <config.h>
#include <plugins/self.h>
@@ -32,13 +31,13 @@
#include "operands/args.h"
#include "operands/pool.h"
#include "operands/register.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
#include "v35/core.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -100,7 +99,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
result = init_dalvik35_core();
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_arch_dalvik_module_to_python_module();
#endif
diff --git a/plugins/dalvik/operand.c b/plugins/dalvik/operand.c
index a176721..4db8fa9 100644
--- a/plugins/dalvik/operand.c
+++ b/plugins/dalvik/operand.c
@@ -749,7 +749,7 @@ void dalvik_mark_first_operand_as_written(GArchInstruction *instr)
operand = g_arch_instruction_get_operand(instr, 0);
- g_register_operand_mark_as_written(G_REGISTER_OPERAND(operand));
+ g_arch_operand_set_flag(operand, ROF_IS_WRITTEN);
g_object_unref(G_OBJECT(operand));
diff --git a/plugins/dalvik/operands/Makefile.am b/plugins/dalvik/operands/Makefile.am
index 4ce597a..3a4ddc1 100644
--- a/plugins/dalvik/operands/Makefile.am
+++ b/plugins/dalvik/operands/Makefile.am
@@ -1,20 +1,14 @@
noinst_LTLIBRARIES = libdalvikoperands.la
-libdalvikoperands_la_SOURCES = \
- args.h args.c \
- pool.h pool.c \
+libdalvikoperands_la_SOURCES = \
+ args.h args.c \
+ pool.h pool.c \
register.h register.c
+libdalvikoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvikoperands_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
-SUBDIRS =
diff --git a/plugins/dalvik/operands/args.c b/plugins/dalvik/operands/args.c
index 6387092..64f8eea 100644
--- a/plugins/dalvik/operands/args.c
+++ b/plugins/dalvik/operands/args.c
@@ -32,11 +32,14 @@
#include <arch/operand-int.h>
#include <common/sort.h>
+#include <core/columns.h>
#include <core/logs.h>
-#include <gtkext/gtkblockdisplay.h>
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
/* Définition d'un opérande visant une liste d'opérandes Dalvik (instance) */
struct _GDalvikArgsOperand
{
@@ -68,8 +71,13 @@ static void g_dalvik_args_operand_dispose(GDalvikArgsOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *, const GDalvikArgsOperand *);
+static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *, const GDalvikArgsOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *g_dalvik_args_operand_find_inner_operand_path(const GDalvikArgsOperand *, const GArchOperand *);
@@ -80,17 +88,20 @@ static GArchOperand *g_dalvik_args_operand_get_inner_operand_from_path(const GDa
/* Traduit un opérande en version humainement lisible. */
static void g_dalvik_args_operand_print(const GDalvikArgsOperand *, GBufferLine *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GArchOperand **g_dalvik_args_operand_list_inner_instances(const GDalvikArgsOperand *, size_t *);
+/* Met à jour une liste de candidats embarqués par un candidat. */
+static void g_dalvik_args_operand_update_inner_instances(GDalvikArgsOperand *, GArchOperand **, size_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
-
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_dalvik_args_operand_hash(const GDalvikArgsOperand *, bool);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_dalvik_args_operand_unserialize(GDalvikArgsOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_dalvik_args_operand_serialize(const GDalvikArgsOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour une liste d'arguments Dalvik. */
@@ -127,8 +138,12 @@ static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass)
operand->print = (operand_print_fc)g_dalvik_args_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_dalvik_args_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_dalvik_args_operand_serialize;
+ operand->list_inner = (operand_list_inners_fc)g_dalvik_args_operand_list_inner_instances;
+ operand->update_inner = (operand_update_inners_fc)g_dalvik_args_operand_update_inner_instances;
+ operand->hash = (operand_hash_fc)g_dalvik_args_operand_hash;
+
+ operand->load = g_arch_operand_load_generic_variadic;
+ operand->store = g_arch_operand_store_generic_variadic;
}
@@ -170,7 +185,7 @@ static void g_dalvik_args_operand_dispose(GDalvikArgsOperand *operand)
size_t i;
for (i = 0; i < operand->count; i++)
- g_object_unref(G_OBJECT(operand->args[i]));
+ g_clear_object(&operand->args[i]);
G_OBJECT_CLASS(g_dalvik_args_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -201,8 +216,102 @@ static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : - *
+* *
+* Description : Crée un réceptacle pour opérandes Dalvik servant d'arguments.*
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_dalvik_args_operand_new(void)
+{
+ GArchOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_DALVIK_ARGS_OPERAND, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à compléter. *
+* arg = nouvel argument pour un appel. *
+* *
+* Description : Ajoute un élément à la liste d'arguments Dalvik. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg)
+{
+ operand->count++;
+ operand->args = realloc(operand->args, operand->count * sizeof(GArchOperand *));
+
+ operand->args[operand->count - 1] = arg;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à compléter. *
+* *
+* Description : Fournit le nombre d'arguments pris en charge. *
+* *
+* Retour : Nombre positif ou nul. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_dalvik_args_count(const GDalvikArgsOperand *operand)
+{
+ return operand->count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à compléter. *
+* index = indice de l'argument recherché. *
+* *
+* Description : Founit un élément de la liste d'arguments Dalvik. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *operand, size_t index)
+{
+ assert(index < operand->count);
+
+ return operand->args[index];
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -212,10 +321,13 @@ static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *operand)
* *
******************************************************************************/
-static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *a, const GDalvikArgsOperand *b)
+static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *a, const GDalvikArgsOperand *b, bool lock)
{
int result; /* Bilan à renvoyer */
+ operand_extra_data_t *ea; /* Données insérées à consulter*/
+ operand_extra_data_t *eb; /* Données insérées à consulter*/
size_t i; /* Boucle de parcours */
+ GArchOperandClass *class; /* Classe parente normalisée */
/* Création de l'objet... */
if (b == NULL)
@@ -223,11 +335,32 @@ static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *a, const GDal
else
{
+ ea = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(a));
+ eb = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(b));
+
+ if (lock)
+ {
+ LOCK_GOBJECT_EXTRA(ea);
+ LOCK_GOBJECT_EXTRA(eb);
+ }
+
result = sort_unsigned_long(a->count, b->count);
for (i = 0; i < a->count && result == 0; i++)
result = g_arch_operand_compare(a->args[i], b->args[i]);
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_dalvik_args_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
+
+ if (lock)
+ {
+ UNLOCK_GOBJECT_EXTRA(eb);
+ UNLOCK_GOBJECT_EXTRA(ea);
+ }
+
}
return result;
@@ -398,75 +531,44 @@ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *operand, GBuff
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Crée un réceptacle pour opérandes Dalvik servant d'arguments.*
+* Description : Fournit une liste de candidats embarqués par un candidat. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Liste de candidats internes ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_dalvik_args_operand_new(void)
+static GArchOperand **g_dalvik_args_operand_list_inner_instances(const GDalvikArgsOperand *operand, size_t *count)
{
- GArchOperand *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_DALVIK_ARGS_OPERAND, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à compléter. *
-* arg = nouvel argument pour un appel. *
-* *
-* Description : Ajoute un élément à la liste d'arguments Dalvik. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg)
-{
- operand->count++;
- operand->args = (GArchOperand **)realloc(operand->args, operand->count * sizeof(GArchOperand *));
-
- operand->args[operand->count - 1] = arg;
+ GArchOperand **result; /* Instances à retourner */
+ size_t i; /* Boucle de parcours */
-}
+ *count = operand->count;
+ result = malloc(*count * sizeof(GArchOperand *));
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à compléter. *
-* *
-* Description : Fournit le nombre d'arguments pris en charge. *
-* *
-* Retour : Nombre positif ou nul. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ for (i = 0; i < *count; i++)
+ {
+ result[i] = operand->args[i];
+ g_object_ref(G_OBJECT(result[i]));
+ }
-size_t g_dalvik_args_count(const GDalvikArgsOperand *operand)
-{
- return operand->count;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : operand = opérande à compléter. *
-* index = indice de l'argument recherché. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* instances = liste de candidats internes devenus singletons. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Founit un élément de la liste d'arguments Dalvik. *
+* Description : Met à jour une liste de candidats embarqués par un candidat. *
* *
* Retour : - *
* *
@@ -474,97 +576,56 @@ size_t g_dalvik_args_count(const GDalvikArgsOperand *operand)
* *
******************************************************************************/
-GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *operand, size_t index)
+static void g_dalvik_args_operand_update_inner_instances(GDalvikArgsOperand *operand, GArchOperand **instances, size_t count)
{
- assert(index < operand->count);
-
- return operand->args[index];
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un opérande depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_dalvik_args_operand_unserialize(GDalvikArgsOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- size_t count; /* Nombre d'opérandes à charger*/
size_t i; /* Boucle de parcours */
- GArchOperand *arg; /* Nouvel argument à intégrer */
- parent = G_ARCH_OPERAND_CLASS(g_dalvik_args_operand_parent_class);
-
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
+ for (i = 0; i < count; i++)
+ g_object_unref(G_OBJECT(operand->args[i]));
- if (result)
- result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true);
+ operand->count = count;
+ operand->args = realloc(operand->args, operand->count * sizeof(GArchOperand *));
- for (i = 0; i < count && result; i++)
+ for (i = 0; i < count; i++)
{
- arg = g_arch_operand_load(storage, format, pbuf);
-
- if (arg == NULL)
- result = false;
-
- else
- g_dalvik_args_operand_add(operand, arg);
-
+ operand->args[i] = instances[i];
+ g_object_ref(G_OBJECT(instances[i]));
}
- return result;
-
}
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_dalvik_args_operand_serialize(const GDalvikArgsOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static guint g_dalvik_args_operand_hash(const GDalvikArgsOperand *operand, bool lock)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- size_t i; /* Boucle de parcours */
+ guint result; /* Valeur à retourner */
+ operand_extra_data_t *extra; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+
+ extra = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(operand));
- parent = G_ARCH_OPERAND_CLASS(g_dalvik_args_operand_parent_class);
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ class = G_ARCH_OPERAND_CLASS(g_dalvik_args_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- if (result)
- result = extend_packed_buffer(pbuf, &operand->count, sizeof(size_t), true);
+ result ^= operand->count;
- for (i = 0; i < operand->count && result; i++)
- result = g_arch_operand_store(operand->args[i], storage, pbuf);
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
return result;
diff --git a/plugins/dalvik/operands/pool.c b/plugins/dalvik/operands/pool.c
index 89bee99..5b99b45 100644
--- a/plugins/dalvik/operands/pool.c
+++ b/plugins/dalvik/operands/pool.c
@@ -34,18 +34,30 @@
#include <arch/operand-int.h>
#include <arch/operands/targetable-int.h>
#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
#include <plugins/dex/pool.h>
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
+
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _dpoolop_extra_data_t
+{
+ operand_extra_data_t parent; /* A laisser en premier */
+
+ DalvikPoolType type; /* Type de table visée */
+
+} dpoolop_extra_data_t;
+
+
/* Définition d'un opérande visant un élément de table de constantes Dalvik (instance) */
struct _GDalvikPoolOperand
{
GArchOperand parent; /* Instance parente */
GDexFormat *format; /* Lien vers le contenu réel */
- DalvikPoolType type; /* Type de table visée */
uint32_t index; /* Indice de l'élément visé */
};
@@ -59,6 +71,21 @@ struct _GDalvikPoolOperandClass
};
+/**
+ * Accès aux informations éventuellement déportées.
+ */
+
+#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+
+# define GET_DALVIK_POOL_OP_EXTRA(op) ((dpoolop_extra_data_t *)&((GArchOperand *)op)->extra)
+
+#else
+
+# define GET_DALVIK_POOL_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), dpoolop_extra_data_t)
+
+#endif
+
+
/* Initialise la classe des opérandes de constante Dalvik. */
static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *);
@@ -74,22 +101,28 @@ static void g_dalvik_pool_operand_dispose(GDalvikPoolOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_dalvik_pool_operand_finalize(GDalvikPoolOperand *);
-/* Compare un opérande avec un autre. */
-static int g_dalvik_pool_operand_compare(const GDalvikPoolOperand *, const GDalvikPoolOperand *);
+/* Indique la nature de la table de constantes visée ici. */
+static DalvikPoolType _g_dalvik_pool_operand_get_pool_type(const GDalvikPoolOperand *, bool);
+
-/* Traduit un opérande en version humainement lisible. */
-static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *, GBufferLine *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Compare un opérande avec un autre. */
+static int g_dalvik_pool_operand_compare(const GDalvikPoolOperand *, const GDalvikPoolOperand *, bool);
+
+/* Traduit un opérande en version humainement lisible. */
+static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *, GBufferLine *);
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_dalvik_pool_operand_hash(const GDalvikPoolOperand *, bool);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_dalvik_pool_operand_unserialize(GDalvikPoolOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_dalvik_pool_operand_load(GDalvikPoolOperand *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_dalvik_pool_operand_serialize(const GDalvikPoolOperand *, GAsmStorage *, packed_buffer_t *);
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_dalvik_pool_operand_store(GDalvikPoolOperand *, GObjectStorage *, packed_buffer_t *);
@@ -101,6 +134,11 @@ static bool g_dalvik_pool_operand_get_addr(const GDalvikPoolOperand *, const vmp
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
+
+
/* Indique le type défini par la GLib pour un un élément de table de constantes Dalvik. */
G_DEFINE_TYPE_WITH_CODE(GDalvikPoolOperand, g_dalvik_pool_operand, G_TYPE_ARCH_OPERAND,
G_IMPLEMENT_INTERFACE(G_TYPE_TARGETABLE_OPERAND, g_dalvik_pool_operand_targetable_interface_init));
@@ -133,8 +171,10 @@ static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass)
operand->compare = (operand_compare_fc)g_dalvik_pool_operand_compare;
operand->print = (operand_print_fc)g_dalvik_pool_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_dalvik_pool_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_dalvik_pool_operand_serialize;
+ operand->hash = (operand_hash_fc)g_dalvik_pool_operand_hash;
+
+ operand->load = (load_operand_fc)g_dalvik_pool_operand_load;
+ operand->store = (store_operand_fc)g_dalvik_pool_operand_store;
}
@@ -191,8 +231,7 @@ static void g_dalvik_pool_operand_targetable_interface_init(GTargetableOperandIn
static void g_dalvik_pool_operand_dispose(GDalvikPoolOperand *operand)
{
- if (operand->format != NULL)
- g_object_unref(G_OBJECT(operand->format));
+ g_clear_object(&operand->format);
G_OBJECT_CLASS(g_dalvik_pool_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -220,8 +259,155 @@ static void g_dalvik_pool_operand_finalize(GDalvikPoolOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : format = format du fichier contenant le code. *
+* type = type de table visée avec la référence. *
+* content = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* size = taille de l'opérande, et donc du registre. *
+* endian = ordre des bits dans la source. *
+* *
+* Description : Crée un opérande visant un élément constant Dalvik. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_dalvik_pool_operand_new(GDexFormat *format, DalvikPoolType type, const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian)
+{
+ GDalvikPoolOperand *result; /* Structure à retourner */
+ uint16_t index16; /* Indice sur 16 bits */
+ uint32_t index32; /* Indice sur 32 bits */
+ bool test; /* Bilan de lecture */
+ dpoolop_extra_data_t *extra; /* Données insérées à modifier */
+
+ switch (size)
+ {
+ case MDS_16_BITS:
+ test = g_binary_content_read_u16(content, pos, endian, &index16);
+ break;
+ case MDS_32_BITS:
+ test = g_binary_content_read_u32(content, pos, endian, &index32);
+ break;
+ default:
+ test = false;
+ break;
+ }
+
+ if (!test)
+ goto gdpon_exit;
+
+ result = g_object_new(G_TYPE_DALVIK_POOL_OPERAND, NULL);
+
+ extra = GET_DALVIK_POOL_OP_EXTRA(result);
+
+ extra->type = type;
+
+ result->format = format;
+ g_object_ref(G_OBJECT(format));
+
+ result->index = (size == MDS_16_BITS ? index16 : index32);
+
+ return G_ARCH_OPERAND(result);
+
+ gdpon_exit:
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
+* *
+* Description : Indique la nature de la table de constantes visée ici. *
+* *
+* Retour : Type de table constantes visée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static DalvikPoolType _g_dalvik_pool_operand_get_pool_type(const GDalvikPoolOperand *operand, bool lock)
+{
+ DalvikPoolType result; /* Type à retourner */
+ dpoolop_extra_data_t *extra; /* Données insérées à consulter*/
+
+ extra = GET_DALVIK_POOL_OP_EXTRA(operand);
+
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
+
+ result = extra->type;
+
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Indique la nature de la table de constantes visée ici. *
+* *
+* Retour : Type de table constantes visée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+DalvikPoolType g_dalvik_pool_operand_get_pool_type(const GDalvikPoolOperand *operand)
+{
+ DalvikPoolType result; /* Type à retourner */
+
+ result = _g_dalvik_pool_operand_get_pool_type(operand, true);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Indique l'indice de l'élément dans la table de constantes. *
+* *
+* Retour : Indice de l'élément visé dans la table de constantes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+uint32_t g_dalvik_pool_operand_get_index(const GDalvikPoolOperand *operand)
+{
+ uint32_t result; /* Indice à retourner */
+
+ result = operand->index;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -231,18 +417,42 @@ static void g_dalvik_pool_operand_finalize(GDalvikPoolOperand *operand)
* *
******************************************************************************/
-static int g_dalvik_pool_operand_compare(const GDalvikPoolOperand *a, const GDalvikPoolOperand *b)
+static int g_dalvik_pool_operand_compare(const GDalvikPoolOperand *a, const GDalvikPoolOperand *b, bool lock)
{
int result; /* Bilan à renvoyer */
+ dpoolop_extra_data_t *ea; /* Données insérées à consulter*/
+ dpoolop_extra_data_t *eb; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+
+ ea = GET_DALVIK_POOL_OP_EXTRA(a);
+ eb = GET_DALVIK_POOL_OP_EXTRA(b);
+
+ if (lock)
+ {
+ LOCK_GOBJECT_EXTRA(ea);
+ LOCK_GOBJECT_EXTRA(eb);
+ }
result = sort_unsigned_long((unsigned long)a->format, (unsigned long)b->format);
if (result == 0)
- result = sort_unsigned_long(a->type, b->type);
+ result = sort_unsigned_long(ea->type, eb->type);
if (result == 0)
result = sort_unsigned_long(a->index, b->index);
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
+
+ if (lock)
+ {
+ UNLOCK_GOBJECT_EXTRA(eb);
+ UNLOCK_GOBJECT_EXTRA(ea);
+ }
+
return result;
}
@@ -264,6 +474,7 @@ static int g_dalvik_pool_operand_compare(const GDalvikPoolOperand *a, const GDal
static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBufferLine *line)
{
GDexPool *pool; /* Table de ressources */
+ DalvikPoolType pool_type; /* Type de table visé */
const char *string; /* Chaîne de caractères #1 */
GDataType *type; /* Type à représenter */
size_t len; /* Taille du texte à créer */
@@ -274,7 +485,9 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
pool = g_dex_format_get_pool(operand->format);
- switch (operand->type)
+ pool_type = g_dalvik_pool_operand_get_pool_type(operand);
+
+ switch (pool_type)
{
case DPT_NONE:
g_buffer_line_append_text(line, DLC_ASSEMBLY, "????", 4, RTT_ERROR, NULL);
@@ -435,140 +648,102 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff
/******************************************************************************
* *
-* Paramètres : format = format du fichier contenant le code. *
-* type = type de table visée avec la référence. *
-* content = flux de données à analyser. *
-* pos = position courante dans ce flux. [OUT] *
-* size = taille de l'opérande, et donc du registre. *
-* endian = ordre des bits dans la source. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Crée un opérande visant un élément constant Dalvik. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_dalvik_pool_operand_new(GDexFormat *format, DalvikPoolType type, const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian)
+static guint g_dalvik_pool_operand_hash(const GDalvikPoolOperand *operand, bool lock)
{
- GDalvikPoolOperand *result; /* Structure à retourner */
- uint16_t index16; /* Indice sur 16 bits */
- uint32_t index32; /* Indice sur 32 bits */
- bool test; /* Bilan de lecture */
-
- switch (size)
- {
- case MDS_16_BITS:
- test = g_binary_content_read_u16(content, pos, endian, &index16);
- break;
- case MDS_32_BITS:
- test = g_binary_content_read_u32(content, pos, endian, &index32);
- break;
- default:
- test = false;
- break;
- }
-
- if (!test)
- goto gdpon_exit;
+ guint result; /* Valeur à retourner */
+ dpoolop_extra_data_t *extra; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+ DalvikPoolType type; /* Type porté par l'opérande */
+ uint32_t index; /* Indice de l'élément */
- result = g_object_new(G_TYPE_DALVIK_POOL_OPERAND, NULL);
+ extra = GET_DALVIK_POOL_OP_EXTRA(G_DALVIK_POOL_OPERAND(operand));
- g_object_ref(G_OBJECT(format));
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- result->format = format;
- result->type = type;
- result->index = (size == MDS_16_BITS ? index16 : index32);
+ class = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- return G_ARCH_OPERAND(result);
+ result ^= g_direct_hash(operand->format);
- gdpon_exit:
+ type = _g_dalvik_pool_operand_get_pool_type(operand, !lock);
- return NULL;
+ result ^= type;
-}
+ index = g_dalvik_pool_operand_get_index(operand);
+ result ^= index;
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique la nature de la table de constantes visée ici. *
-* *
-* Retour : Type de table constantes visée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
-DalvikPoolType g_dalvik_pool_operand_get_pool_type(const GDalvikPoolOperand *operand)
-{
- return operand->type;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : operand = opérande à consulter. *
+* Paramètres : operand = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
* *
-* Description : Indique l'indice de l'élément dans la table de constantes. *
+* Description : Charge un contenu depuis une mémoire tampon. *
* *
-* Retour : Indice de l'élément visé dans la table de constantes. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-uint32_t g_dalvik_pool_operand_get_index(const GDalvikPoolOperand *operand)
+static bool g_dalvik_pool_operand_load(GDalvikPoolOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
- return operand->index;
-
-}
+ bool result; /* Bilan à retourner */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+ dpoolop_extra_data_t *extra; /* Données insérées à modifier */
+ uleb128_t value; /* Valeur ULEB128 à charger */
+ parent = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class);
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
+ if (result)
+ {
+ extra = GET_DALVIK_POOL_OP_EXTRA(operand);
+ LOCK_GOBJECT_EXTRA(extra);
-/******************************************************************************
-* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge un opérande depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result = unpack_uleb128(&value, pbuf);
-static bool g_dalvik_pool_operand_unserialize(GDalvikPoolOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
+ if (result)
+ extra->type = value;
- parent = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class);
+ UNLOCK_GOBJECT_EXTRA(extra);
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
+ }
if (result)
{
- operand->format = G_DEX_FORMAT(format);
- g_object_ref(G_OBJECT(format));
+ operand->format = get_storage_linked_format(storage);
+ result = G_IS_DEX_FORMAT(operand->format);
}
if (result)
- result = extract_packed_buffer(pbuf, &operand->type, sizeof(DalvikPoolType), true);
+ result = unpack_uleb128(&value, pbuf);
if (result)
- result = extract_packed_buffer(pbuf, &operand->index, sizeof(uint32_t), true);
+ operand->index = value;
return result;
@@ -577,11 +752,11 @@ static bool g_dalvik_pool_operand_unserialize(GDalvikPoolOperand *operand, GAsmS
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -589,20 +764,30 @@ static bool g_dalvik_pool_operand_unserialize(GDalvikPoolOperand *operand, GAsmS
* *
******************************************************************************/
-static bool g_dalvik_pool_operand_serialize(const GDalvikPoolOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_dalvik_pool_operand_store(GDalvikPoolOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchOperandClass *parent; /* Classe parente à consulter */
+ dpoolop_extra_data_t *extra; /* Données insérées à modifier */
parent = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class);
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
if (result)
- result = extend_packed_buffer(pbuf, &operand->type, sizeof(DalvikPoolType), true);
+ {
+ extra = GET_DALVIK_POOL_OP_EXTRA(operand);
+
+ LOCK_GOBJECT_EXTRA(extra);
+
+ result = pack_uleb128((uleb128_t []){ extra->type }, pbuf);
+
+ UNLOCK_GOBJECT_EXTRA(extra);
+
+ }
if (result)
- result = extend_packed_buffer(pbuf, &operand->index, sizeof(uint32_t), true);
+ result = pack_uleb128((uleb128_t []){ operand->index }, pbuf);
return result;
@@ -634,6 +819,7 @@ static bool g_dalvik_pool_operand_serialize(const GDalvikPoolOperand *operand, G
static bool g_dalvik_pool_operand_get_addr(const GDalvikPoolOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr)
{
bool result; /* Bilan à retourner */
+ DalvikPoolType type; /* Type de table visé */
GDexPool *pool; /* Table de ressources */
GDexMethod *method; /* Méthode ciblée ici */
GBinRoutine *routine; /* Routine liée à la méthode */
@@ -641,7 +827,9 @@ static bool g_dalvik_pool_operand_get_addr(const GDalvikPoolOperand *operand, co
result = false;
- if (operand->type == DPT_METHOD)
+ type = g_dalvik_pool_operand_get_pool_type(operand);
+
+ if (type == DPT_METHOD)
{
pool = g_dex_format_get_pool(G_DEX_FORMAT(format));
diff --git a/plugins/dalvik/pseudo/Makefile.am b/plugins/dalvik/pseudo/Makefile.am
index 687aa72..74cc574 100644
--- a/plugins/dalvik/pseudo/Makefile.am
+++ b/plugins/dalvik/pseudo/Makefile.am
@@ -1,19 +1,14 @@
noinst_LTLIBRARIES = libdalvikpseudo.la
-libdalvikpseudo_la_SOURCES = \
- fill.h fill.c \
- identifiers.h \
+libdalvikpseudo_la_SOURCES = \
+ fill.h fill.c \
+ identifiers.h \
switch.h switch.c
-libdalvikpseudo_la_LIBADD =
+libdalvikpseudo_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvikpseudo_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dalvik/python/Makefile.am b/plugins/dalvik/python/Makefile.am
index 90c8924..74fe00d 100644
--- a/plugins/dalvik/python/Makefile.am
+++ b/plugins/dalvik/python/Makefile.am
@@ -1,15 +1,16 @@
noinst_LTLIBRARIES = libdalvikpython.la
-libdalvikpython_la_SOURCES = \
- instruction.h instruction.c \
- module.h module.c \
+libdalvikpython_la_SOURCES = \
+ instruction.h instruction.c \
+ module.h module.c \
processor.h processor.c
-libdalvikpython_la_LIBADD = \
+libdalvikpython_la_LIBADD = \
v35/libdalvikpythonv35.la
-libdalvikpython_la_LDFLAGS =
+libdalvikpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -17,9 +18,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvikpython_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = v35
diff --git a/plugins/dalvik/python/instruction.c b/plugins/dalvik/python/instruction.c
index c9d039f..a6d4ad4 100644
--- a/plugins/dalvik/python/instruction.c
+++ b/plugins/dalvik/python/instruction.c
@@ -102,7 +102,10 @@ bool register_python_dalvik_instruction(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DALVIK_INSTRUCTION, type, get_python_arch_instruction_type()))
+ if (!ensure_python_arch_instruction_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DALVIK_INSTRUCTION, type))
return false;
return true;
diff --git a/plugins/dalvik/python/processor.c b/plugins/dalvik/python/processor.c
index 26fd8b7..9885a04 100644
--- a/plugins/dalvik/python/processor.c
+++ b/plugins/dalvik/python/processor.c
@@ -100,7 +100,10 @@ bool register_python_dalvik_processor(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DALVIK_PROCESSOR, type, get_python_arch_processor_type()))
+ if (!ensure_python_arch_processor_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DALVIK_PROCESSOR, type))
return false;
return true;
diff --git a/plugins/dalvik/python/v35/Makefile.am b/plugins/dalvik/python/v35/Makefile.am
index 3dda5c1..4464dcc 100644
--- a/plugins/dalvik/python/v35/Makefile.am
+++ b/plugins/dalvik/python/v35/Makefile.am
@@ -1,20 +1,15 @@
noinst_LTLIBRARIES = libdalvikpythonv35.la
-libdalvikpythonv35_la_SOURCES = \
- instruction.h instruction.c \
- module.h module.c \
+libdalvikpythonv35_la_SOURCES = \
+ instruction.h instruction.c \
+ module.h module.c \
processor.h processor.c
-libdalvikpythonv35_la_LDFLAGS =
+libdalvikpythonv35_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvikpythonv35_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dalvik/python/v35/instruction.c b/plugins/dalvik/python/v35/instruction.c
index f5ccc2c..7373e77 100644
--- a/plugins/dalvik/python/v35/instruction.c
+++ b/plugins/dalvik/python/v35/instruction.c
@@ -100,8 +100,9 @@ bool register_python_dalvik35_instruction(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DALVIK35_INSTRUCTION,
- type, get_python_dalvik_instruction_type()))
+ /* TODO : ensure get_python_dalvik_instruction_type() */
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DALVIK35_INSTRUCTION, type))
return false;
return true;
diff --git a/plugins/dalvik/python/v35/processor.c b/plugins/dalvik/python/v35/processor.c
index fea342b..8df8249 100644
--- a/plugins/dalvik/python/v35/processor.c
+++ b/plugins/dalvik/python/v35/processor.c
@@ -100,8 +100,9 @@ bool register_python_dalvik35_processor(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DALVIK35_PROCESSOR,
- type, get_python_dalvik_processor_type()))
+ /* TODO : ensure get_python_dalvik_processor_type() */
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DALVIK35_PROCESSOR, type))
return false;
return true;
diff --git a/plugins/dalvik/register.c b/plugins/dalvik/register.c
index 87babfb..8413108 100644
--- a/plugins/dalvik/register.c
+++ b/plugins/dalvik/register.c
@@ -30,7 +30,7 @@
#include <arch/register-int.h>
#include <common/sort.h>
-#include <gtkext/gtkblockdisplay.h>
+#include <core/columns.h>
@@ -70,25 +70,28 @@ static void g_dalvik_register_dispose(GDalvikRegister *);
/* Procède à la libération totale de la mémoire. */
static void g_dalvik_register_finalize(GDalvikRegister *);
-/* Produit une empreinte à partir d'un registre. */
-static guint g_dalvik_register_hash(const GDalvikRegister *);
-
-/* Traduit un registre en version humainement lisible. */
-static void g_dalvik_register_print(const GDalvikRegister *, GBufferLine *);
-
/* Crée une réprésentation de registre Dalvik. */
static GArchRegister *_g_dalvik_register_new(uint16_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Produit une empreinte à partir d'un registre. */
+static guint g_dalvik_register_hash(const GDalvikRegister *);
+/* Compare un registre avec un autre. */
+static int g_dalvik_register_compare(const GDalvikRegister *, const GDalvikRegister *);
+
+/* Traduit un registre en version humainement lisible. */
+static void g_dalvik_register_print(const GDalvikRegister *, GBufferLine *);
-/* Charge un registre depuis une mémoire tampon. */
-static GArchRegister *g_dalvik_register_unserialize(GDalvikRegister *, GAsmStorage *, packed_buffer_t *);
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_dalvik_register_load(GDalvikRegister *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un registre dans une mémoire tampon. */
-static bool g_dalvik_register_serialize(const GDalvikRegister *, GAsmStorage *, packed_buffer_t *);
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_dalvik_register_store(GDalvikRegister *, GObjectStorage *, packed_buffer_t *);
@@ -130,20 +133,21 @@ G_DEFINE_TYPE(GDalvikRegister, g_dalvik_register, G_TYPE_ARCH_REGISTER);
static void g_dalvik_register_class_init(GDalvikRegisterClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchRegisterClass *reg_class; /* Classe de haut niveau */
+ GArchRegisterClass *reg; /* Classe de haut niveau */
object = G_OBJECT_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_register_dispose;
object->finalize = (GObjectFinalizeFunc)g_dalvik_register_finalize;
- reg_class = G_ARCH_REGISTER_CLASS(klass);
+ reg = G_ARCH_REGISTER_CLASS(klass);
+
+ reg->hash = (reg_hash_fc)g_dalvik_register_hash;
+ reg->compare = (reg_compare_fc)g_dalvik_register_compare;
+ reg->print = (reg_print_fc)g_dalvik_register_print;
- reg_class->hash = (reg_hash_fc)g_dalvik_register_hash;
- reg_class->compare = (reg_compare_fc)g_dalvik_register_compare;
- reg_class->print = (reg_print_fc)g_dalvik_register_print;
- reg_class->unserialize = (reg_unserialize_fc)g_dalvik_register_unserialize;
- reg_class->serialize = (reg_serialize_fc)g_dalvik_register_serialize;
+ reg->load = (load_register_fc)g_dalvik_register_load;
+ reg->store = (store_register_fc)g_dalvik_register_store;
}
@@ -206,50 +210,6 @@ static void g_dalvik_register_finalize(GDalvikRegister *reg)
/******************************************************************************
* *
-* Paramètres : reg = opérande à consulter pour le calcul. *
-* *
-* Description : Produit une empreinte à partir d'un registre. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static guint g_dalvik_register_hash(const GDalvikRegister *reg)
-{
- return reg->index;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = registre à transcrire. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un registre en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dalvik_register_print(const GDalvikRegister *reg, GBufferLine *line)
-{
- char key[MAX_REGNAME_LEN]; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
-
- klen = snprintf(key, MAX_REGNAME_LEN, "v%hu", reg->index);
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : index = indice du registre correspondant. *
* *
* Description : Crée une réprésentation de registre Dalvik. *
@@ -315,6 +275,31 @@ uint16_t g_dalvik_register_get_index(const GDalvikRegister *reg)
}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : reg = opérande à consulter pour le calcul. *
+* *
+* Description : Produit une empreinte à partir d'un registre. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static guint g_dalvik_register_hash(const GDalvikRegister *reg)
+{
+ return reg->index;
+
+}
+
+
/******************************************************************************
* *
* Paramètres : a = premier opérande à consulter. *
@@ -328,7 +313,7 @@ uint16_t g_dalvik_register_get_index(const GDalvikRegister *reg)
* *
******************************************************************************/
-int g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b)
+static int g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b)
{
int result; /* Bilan à retourner */
@@ -339,57 +324,56 @@ int g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b
}
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : reg = registre d'architecture à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : reg = registre à transcrire. *
+* line = ligne tampon où imprimer l'opérande donné. *
* *
-* Description : Charge un registre depuis une mémoire tampon. *
+* Description : Traduit un registre en version humainement lisible. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GArchRegister *g_dalvik_register_unserialize(GDalvikRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
+static void g_dalvik_register_print(const GDalvikRegister *reg, GBufferLine *line)
{
- GArchRegister *result; /* Instance à retourner */
- uint16_t index; /* Indice du registre */
- bool status; /* Bilan d'une extraction */
- GArchRegisterClass *parent; /* Classe parente à consulter */
+ char key[MAX_REGNAME_LEN]; /* Mot clef principal */
+ size_t klen; /* Taille de ce mot clef */
- status = extract_packed_buffer(pbuf, &index, sizeof(uint16_t), true);
+ klen = snprintf(key, MAX_REGNAME_LEN, "v%hu", reg->index);
- if (status)
- {
- result = get_dalvik_register(index);
+ g_buffer_line_append_text(line, DLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL);
- if (result == NULL)
- g_object_unref(G_OBJECT(reg));
+}
- }
- else
- {
- g_object_unref(G_OBJECT(reg));
- result = NULL;
- }
+/******************************************************************************
+* *
+* Paramètres : reg = élément GLib à constuire. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à lire. *
+* *
+* Description : Charge un contenu depuis une mémoire tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- if (result != NULL)
- {
- parent = G_ARCH_REGISTER_CLASS(g_dalvik_register_parent_class);
+static bool g_dalvik_register_load(GDalvikRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GArchRegisterClass *parent; /* Classe parente à consulter */
- result = parent->unserialize(result, storage, pbuf);
+ parent = G_ARCH_REGISTER_CLASS(g_dalvik_register_parent_class);
- }
+ result = parent->load(G_ARCH_REGISTER(reg), storage, pbuf);
+
+ if (result)
+ result = extract_packed_buffer(pbuf, &reg->index, sizeof(uint16_t), true);
return result;
@@ -398,11 +382,11 @@ static GArchRegister *g_dalvik_register_unserialize(GDalvikRegister *reg, GAsmSt
/******************************************************************************
* *
-* Paramètres : reg = registre d'architecture à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
+* Paramètres : reg = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
* pbuf = zone tampon à remplir. *
* *
-* Description : Sauvegarde un registre dans une mémoire tampon. *
+* Description : Sauvegarde un contenu dans une mémoire tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -410,20 +394,17 @@ static GArchRegister *g_dalvik_register_unserialize(GDalvikRegister *reg, GAsmSt
* *
******************************************************************************/
-static bool g_dalvik_register_serialize(const GDalvikRegister *reg, GAsmStorage *storage, packed_buffer_t *pbuf)
+static bool g_dalvik_register_store(GDalvikRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
GArchRegisterClass *parent; /* Classe parente à consulter */
- result = extend_packed_buffer(pbuf, &reg->index, sizeof(uint16_t), true);
+ parent = G_ARCH_REGISTER_CLASS(g_dalvik_register_parent_class);
- if (result)
- {
- parent = G_ARCH_REGISTER_CLASS(g_dalvik_register_parent_class);
+ result = parent->store(G_ARCH_REGISTER(reg), storage, pbuf);
- result = parent->serialize(G_ARCH_REGISTER(reg), storage, pbuf);
-
- }
+ if (result)
+ result = extend_packed_buffer(pbuf, &reg->index, sizeof(uint16_t), true);
return result;
diff --git a/plugins/dalvik/register.h b/plugins/dalvik/register.h
index 586d242..8c664a5 100644
--- a/plugins/dalvik/register.h
+++ b/plugins/dalvik/register.h
@@ -60,9 +60,6 @@ GArchRegister *g_dalvik_register_new(uint16_t);
/* Fournit l'indice d'un registre Dalvik. */
uint16_t g_dalvik_register_get_index(const GDalvikRegister *);
-/* Compare un registre avec un autre. */
-int g_dalvik_register_compare(const GDalvikRegister *, const GDalvikRegister *);
-
/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */
diff --git a/plugins/dalvik/v35/Makefile.am b/plugins/dalvik/v35/Makefile.am
index 8a7be09..73e09a0 100644
--- a/plugins/dalvik/v35/Makefile.am
+++ b/plugins/dalvik/v35/Makefile.am
@@ -1,13 +1,15 @@
noinst_LTLIBRARIES = libdalvik35.la
-libdalvik35_la_SOURCES = \
- core.h core.c \
- instruction.h instruction.c \
- operand.h \
+libdalvik35_la_SOURCES = \
+ core.h core.c \
+ instruction.h instruction.c \
+ operand.h \
processor.h processor.c
-libdalvik35_la_LIBADD = \
+libdalvik35_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+libdalvik35_la_LIBADD = \
opcodes/libdalvik35opcodes.la
@@ -16,9 +18,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvik35_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
SUBDIRS = opdefs opcodes
diff --git a/plugins/dalvik/v35/opcodes/Makefile.am b/plugins/dalvik/v35/opcodes/Makefile.am
index fd26224..8a766f9 100644
--- a/plugins/dalvik/v35/opcodes/Makefile.am
+++ b/plugins/dalvik/v35/opcodes/Makefile.am
@@ -13,7 +13,7 @@ noinst_LTLIBRARIES = libdalvik35opcodes.la
libdalvik35opcodes_la_SOURCES = $(GENERATED_FILES)
-libdalvik35opcodes_la_LIBADD =
+libdalvik35opcodes_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
@@ -21,11 +21,6 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdalvik35opcodes_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
CLEANFILES = $(GENERATED_FILES)
dist-hook:
diff --git a/plugins/devdbg/Makefile.am b/plugins/devdbg/Makefile.am
index a92744d..0bf81c6 100644
--- a/plugins/devdbg/Makefile.am
+++ b/plugins/devdbg/Makefile.am
@@ -11,9 +11,11 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs'
endif
-libspeed_la_SOURCES = \
+libspeed_la_SOURCES = \
speed.h speed.c
+libspeed_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libspeed_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -23,8 +25,3 @@ libspeed_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libspeed_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dex/Makefile.am b/plugins/dex/Makefile.am
index 8eb7bde..a587fe2 100644
--- a/plugins/dex/Makefile.am
+++ b/plugins/dex/Makefile.am
@@ -35,21 +35,23 @@ PYTHON3_SUBDIRS = python
endif
-libdex_la_SOURCES = \
- core.h core.c \
- class.h class.c \
- dex-int.h dex-int.c \
- dex_def.h \
- field.h field.c \
- format.h format.c \
- loading.h loading.c \
- method.h method.c \
- pool.h pool.c \
+libdex_la_SOURCES = \
+ core.h core.c \
+ class.h class.c \
+ dex-int.h dex-int.c \
+ dex_def.h \
+ field.h field.c \
+ format.h format.c \
+ loading.h loading.c \
+ method.h method.c \
+ pool.h pool.c \
routine.h routine.c
-libdex_la_LIBADD = \
+libdex_la_LIBADD = \
$(PYTHON3_LIBADD)
+libdex_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libdex_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -61,8 +63,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdex_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/dex/core.c b/plugins/dex/core.c
index 22ebfff..1101a89 100644
--- a/plugins/dex/core.c
+++ b/plugins/dex/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/global.h>
#include <plugins/self.h>
#include "format.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
result = add_format_dex_module_to_python_module();
#else
result = true;
diff --git a/plugins/dex/loading.h b/plugins/dex/loading.h
index 5560e4e..4de6df1 100644
--- a/plugins/dex/loading.h
+++ b/plugins/dex/loading.h
@@ -26,9 +26,11 @@
#include <glib-object.h>
+#include <stdbool.h>
+#include <stdint.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c
index 6007019..af591d3 100644
--- a/plugins/dex/pool.c
+++ b/plugins/dex/pool.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include <malloc.h>
+#include <stdlib.h>
#include <string.h>
@@ -1181,6 +1182,10 @@ bool g_dex_pool_load_all_classes(GDexPool *pool, wgroup_id_t gid, GtkStatusStack
size_t scount; /* Quantité de ces symboles */
uint32_t j; /* Boucle de parcours #2 */
size_t k; /* Boucle de parcours #3 */
+ bool need_sort; /* Tri des symboles nécessaire */
+ phys_t last; /* Dernière position rencontrée*/
+ const mrange_t *range; /* Couverture du symbole */
+ const vmpa2t *addr; /* Emplacement du symbole */
result = true;
@@ -1229,8 +1234,38 @@ bool g_dex_pool_load_all_classes(GDexPool *pool, wgroup_id_t gid, GtkStatusStack
result = g_dex_class_get_collect_symbols(pool->classes[j], &symbols, &scount);
if (result)
+ {
+ /**
+ * Si le format DEX impose un ordre croissant dans les identifiants
+ * des méthodes d'une classe (champ method_idx de la structure
+ * encoded_method), cela ne conduit pas forcément à :
+ * - à disposer de champs code_off eux-même ordonnés ;
+ * - à retrouver des ordonnancements d'une classe à une autre.
+ *
+ * Un tri est donc forcé ici s'il s'avère nécessaire.
+ */
+
+ need_sort = false;
+ last = VMPA_NO_PHYSICAL;
+
+ for (k = 0; k < scount && !need_sort; k++)
+ {
+ range = g_binary_symbol_get_range(symbols[k]);
+ addr = get_mrange_addr(range);
+
+ need_sort = (last != VMPA_NO_PHYSICAL && last > get_phy_addr(addr));
+
+ last = get_phy_addr(addr);
+
+ }
+
+ if (need_sort)
+ qsort(symbols, count, sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp);
+
result = g_binary_format_add_symbols(G_BIN_FORMAT(pool->format), symbols, count);
+ }
+
for (k = 0; k < scount; k++)
g_object_unref(symbols[k]);
diff --git a/plugins/dex/python/Makefile.am b/plugins/dex/python/Makefile.am
index e91630e..b627157 100644
--- a/plugins/dex/python/Makefile.am
+++ b/plugins/dex/python/Makefile.am
@@ -1,26 +1,21 @@
noinst_LTLIBRARIES = libdexpython.la
-libdexpython_la_SOURCES = \
- class.h class.c \
- constants.h constants.c \
- field.h field.c \
- format.h format.c \
- method.h method.c \
- module.h module.c \
- pool.h pool.c \
- routine.h routine.c \
+libdexpython_la_SOURCES = \
+ class.h class.c \
+ constants.h constants.c \
+ field.h field.c \
+ format.h format.c \
+ method.h method.c \
+ module.h module.c \
+ pool.h pool.c \
+ routine.h routine.c \
translate.h translate.c
-libdexpython_la_LDFLAGS =
+libdexpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdexpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dex/python/class.c b/plugins/dex/python/class.c
index e344124..247197c 100644
--- a/plugins/dex/python/class.c
+++ b/plugins/dex/python/class.c
@@ -584,14 +584,14 @@ PyTypeObject *get_python_dex_class_type(void)
bool register_python_dex_class(PyObject *module)
{
- PyTypeObject *py_dex_class_type; /* Type Python 'DexClass' */
+ PyTypeObject *type; /* Type Python 'DexClass' */
PyObject *dict; /* Dictionnaire du module */
- py_dex_class_type = get_python_dex_class_type();
+ type = get_python_dex_class_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_CLASS, py_dex_class_type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_CLASS, type))
return false;
return true;
diff --git a/plugins/dex/python/field.c b/plugins/dex/python/field.c
index 1381af6..081d0af 100644
--- a/plugins/dex/python/field.c
+++ b/plugins/dex/python/field.c
@@ -181,14 +181,14 @@ PyTypeObject *get_python_dex_field_type(void)
bool register_python_dex_field(PyObject *module)
{
- PyTypeObject *py_dex_field_type; /* Type Python 'DexField' */
+ PyTypeObject *type; /* Type Python 'DexField' */
PyObject *dict; /* Dictionnaire du module */
- py_dex_field_type = get_python_dex_field_type();
+ type = get_python_dex_field_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_FIELD, py_dex_field_type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_FIELD, type))
return false;
return true;
diff --git a/plugins/dex/python/format.c b/plugins/dex/python/format.c
index fa65b25..4a8939b 100644
--- a/plugins/dex/python/format.c
+++ b/plugins/dex/python/format.c
@@ -281,7 +281,10 @@ bool register_python_dex_format(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_FORMAT, type, get_python_executable_format_type()))
+ if (!ensure_python_executable_format_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_FORMAT, type))
return false;
if (!define_python_dex_format_common_constants(type))
diff --git a/plugins/dex/python/method.c b/plugins/dex/python/method.c
index fc56f29..ed67176 100644
--- a/plugins/dex/python/method.c
+++ b/plugins/dex/python/method.c
@@ -291,14 +291,14 @@ PyTypeObject *get_python_dex_method_type(void)
bool register_python_dex_method(PyObject *module)
{
- PyTypeObject *py_dex_method_type; /* Type Python 'DexMethod' */
+ PyTypeObject *type; /* Type Python 'DexMethod' */
PyObject *dict; /* Dictionnaire du module */
- py_dex_method_type = get_python_dex_method_type();
+ type = get_python_dex_method_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_METHOD, py_dex_method_type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_METHOD, type))
return false;
return true;
diff --git a/plugins/dex/python/pool.c b/plugins/dex/python/pool.c
index ddfc900..0c08865 100644
--- a/plugins/dex/python/pool.c
+++ b/plugins/dex/python/pool.c
@@ -822,7 +822,7 @@ bool register_python_dex_pool(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_POOL, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_POOL, type))
return false;
return true;
diff --git a/plugins/dex/python/routine.c b/plugins/dex/python/routine.c
index 31410c7..af38263 100644
--- a/plugins/dex/python/routine.c
+++ b/plugins/dex/python/routine.c
@@ -165,7 +165,10 @@ bool register_python_dex_routine(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_ROUTINE, type, get_python_binary_routine_type()))
+ if (!ensure_python_binary_routine_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_ROUTINE, type))
return false;
return true;
diff --git a/plugins/dexbnf/Makefile.am b/plugins/dexbnf/Makefile.am
index 51598ce..222cc35 100644
--- a/plugins/dexbnf/Makefile.am
+++ b/plugins/dexbnf/Makefile.am
@@ -34,17 +34,19 @@ PYTHON3_SUBDIRS = python
endif
-libdexbnf_la_SOURCES = \
- context.h context.c \
- core.h core.c \
- demangler.h demangler.c \
- simple.h simple.c \
- shorty.h shorty.c \
+libdexbnf_la_SOURCES = \
+ context.h context.c \
+ core.h core.c \
+ demangler.h demangler.c \
+ simple.h simple.c \
+ shorty.h shorty.c \
type.h type.c
-libdexbnf_la_LIBADD = \
+libdexbnf_la_LIBADD = \
$(PYTHON3_LIBADD)
+libdexbnf_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libdexbnf_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -56,8 +58,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdexbnf_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/dexbnf/core.c b/plugins/dexbnf/core.c
index 2b9408a..07e7545 100644
--- a/plugins/dexbnf/core.c
+++ b/plugins/dexbnf/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/demanglers.h>
#include <plugins/self.h>
#include "demangler.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,9 +64,9 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
- result = register_demangler_type("dex", G_TYPE_DEX_DEMANGLER);
+ result = register_demangler_type(G_TYPE_DEX_DEMANGLER);
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_mangling_dexbnf_module_to_python_module();
#endif
diff --git a/plugins/dexbnf/demangler.c b/plugins/dexbnf/demangler.c
index 503f7ce..03f24f7 100644
--- a/plugins/dexbnf/demangler.c
+++ b/plugins/dexbnf/demangler.c
@@ -58,6 +58,9 @@ static void g_dex_demangler_dispose(GDexDemangler *);
/* Procède à la libération totale de la mémoire. */
static void g_dex_demangler_finalize(GDexDemangler *);
+/* Fournit la désignation interne du décodeur de désignations. */
+static char *g_dex_demangler_get_key(const GDexDemangler *);
+
/* Indique le type défini pour un décodeur de désignations. */
@@ -88,6 +91,7 @@ static void g_dex_demangler_class_init(GDexDemanglerClass *klass)
demangler = G_COMP_DEMANGLER_CLASS(klass);
+ demangler->get_key = (get_demangler_key_fc)g_dex_demangler_get_key;
demangler->can_demangle = (can_be_demangled_fc)NULL;
demangler->ns_sep = ".";
@@ -173,3 +177,26 @@ GCompDemangler *g_dex_demangler_new(void)
return G_COMP_DEMANGLER(result);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = décodeur à consulter. *
+* *
+* Description : Fournit la désignation interne du décodeur de désignations. *
+* *
+* Retour : Simple chaîne de caractères. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_dex_demangler_get_key(const GDexDemangler *demangler)
+{
+ char *result; /* Désignation à renvoyer */
+
+ result = strdup("dex");
+
+ return result;
+
+}
diff --git a/plugins/dexbnf/python/Makefile.am b/plugins/dexbnf/python/Makefile.am
index 59668eb..95a8b0c 100644
--- a/plugins/dexbnf/python/Makefile.am
+++ b/plugins/dexbnf/python/Makefile.am
@@ -1,19 +1,14 @@
noinst_LTLIBRARIES = libdexbnfpython.la
-libdexbnfpython_la_SOURCES = \
- demangler.h demangler.c \
+libdexbnfpython_la_SOURCES = \
+ demangler.h demangler.c \
module.h module.c
-libdexbnfpython_la_LDFLAGS =
+libdexbnfpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdexbnfpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dexbnf/python/demangler.c b/plugins/dexbnf/python/demangler.c
index 3682216..8fc93e4 100644
--- a/plugins/dexbnf/python/demangler.c
+++ b/plugins/dexbnf/python/demangler.c
@@ -140,15 +140,17 @@ PyTypeObject *get_python_dex_demangler_type(void)
bool register_python_dex_demangler(PyObject *module)
{
- PyTypeObject *py_dex_demangler_type; /* Type Python 'DexDemangler' */
+ PyTypeObject *type; /* Type Python 'DexDemangler' */
PyObject *dict; /* Dictionnaire du module */
- py_dex_demangler_type = get_python_dex_demangler_type();
+ type = get_python_dex_demangler_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DEX_DEMANGLER,
- py_dex_demangler_type, get_python_compiler_demangler_type()))
+ if (!ensure_python_compiler_demangler_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_DEMANGLER, type))
return false;
return true;
diff --git a/plugins/dwarf/Makefile.am b/plugins/dwarf/Makefile.am
index 5a8c9c9..c93e302 100644
--- a/plugins/dwarf/Makefile.am
+++ b/plugins/dwarf/Makefile.am
@@ -11,15 +11,15 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs'
endif
-libdwarf_la_SOURCES = \
- abbrev.h abbrev.c \
- checks.h checks.c \
- core.h core.c \
- def.h \
- die.h die.c \
- form.h form.c \
- format.h format.c \
- info.h info.c \
+libdwarf_la_SOURCES = \
+ abbrev.h abbrev.c \
+ checks.h checks.c \
+ core.h core.c \
+ def.h \
+ die.h die.c \
+ form.h form.c \
+ format.h format.c \
+ info.h info.c \
utils.h utils.c
@@ -33,11 +33,13 @@ libdwarf_la_SOURCES = \
# info.h info.c \
# symbols.h symbols.c
-libdwarf_la_LIBADD = \
- v2/libdwarfv2.la \
- v3/libdwarfv3.la \
+libdwarf_la_LIBADD = \
+ v2/libdwarfv2.la \
+ v3/libdwarfv3.la \
v4/libdwarfv4.la
+libdwarf_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libdwarf_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -49,8 +51,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdwarf_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = v2 v3 v4
diff --git a/plugins/dwarf/core.c b/plugins/dwarf/core.c
index bf1e812..7b62fb9 100644
--- a/plugins/dwarf/core.c
+++ b/plugins/dwarf/core.c
@@ -24,14 +24,13 @@
#include "core.h"
-#include <config.h>
#include <plugins/self.h>
#include "format.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
diff --git a/plugins/dwarf/info.h b/plugins/dwarf/info.h
index a2fd961..6ce3e9a 100644
--- a/plugins/dwarf/info.h
+++ b/plugins/dwarf/info.h
@@ -29,6 +29,7 @@
#include <glibext/delayed.h>
+#include <glibext/notifier.h>
#include "format.h"
diff --git a/plugins/dwarf/v2/Makefile.am b/plugins/dwarf/v2/Makefile.am
index 1683ded..5664927 100644
--- a/plugins/dwarf/v2/Makefile.am
+++ b/plugins/dwarf/v2/Makefile.am
@@ -1,17 +1,12 @@
noinst_LTLIBRARIES = libdwarfv2.la
-libdwarfv2_la_SOURCES = \
+libdwarfv2_la_SOURCES = \
checks.h checks.c
-libdwarfv2_la_LDFLAGS = $(LIBGTK_LIBS)
+libdwarfv2_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdwarfv2_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dwarf/v3/Makefile.am b/plugins/dwarf/v3/Makefile.am
index b821d2a..2078058 100644
--- a/plugins/dwarf/v3/Makefile.am
+++ b/plugins/dwarf/v3/Makefile.am
@@ -1,17 +1,12 @@
noinst_LTLIBRARIES = libdwarfv3.la
-libdwarfv3_la_SOURCES = \
+libdwarfv3_la_SOURCES = \
checks.h checks.c
-libdwarfv3_la_LDFLAGS = $(LIBGTK_LIBS)
+libdwarfv3_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdwarfv3_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dwarf/v4/Makefile.am b/plugins/dwarf/v4/Makefile.am
index e06e8f5..ef13b2c 100644
--- a/plugins/dwarf/v4/Makefile.am
+++ b/plugins/dwarf/v4/Makefile.am
@@ -1,17 +1,12 @@
noinst_LTLIBRARIES = libdwarfv4.la
-libdwarfv4_la_SOURCES = \
+libdwarfv4_la_SOURCES = \
checks.h checks.c
-libdwarfv4_la_LDFLAGS = $(LIBGTK_LIBS)
+libdwarfv4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libdwarfv4_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/elf/Makefile.am b/plugins/elf/Makefile.am
index 880ae78..677cf93 100644
--- a/plugins/elf/Makefile.am
+++ b/plugins/elf/Makefile.am
@@ -37,23 +37,25 @@ PYTHON3_SUBDIRS = python
endif
-libelf_la_SOURCES = \
- core.h core.c \
- elf-int.h elf-int.c \
- elf_def.h \
- elf_def_arm.h \
- format.h format.c \
- dynamic.h dynamic.c \
- helper_arm.h helper_arm.c \
- loading.h loading.c \
- program.h program.c \
- section.h section.c \
- strings.h strings.c \
+libelf_la_SOURCES = \
+ core.h core.c \
+ elf-int.h elf-int.c \
+ elf_def.h \
+ elf_def_arm.h \
+ format.h format.c \
+ dynamic.h dynamic.c \
+ helper_arm.h helper_arm.c \
+ loading.h loading.c \
+ program.h program.c \
+ section.h section.c \
+ strings.h strings.c \
symbols.h symbols.c
-libelf_la_LIBADD = \
+libelf_la_LIBADD = \
$(PYTHON3_LIBADD)
+libelf_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libelf_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -65,8 +67,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libelf_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/elf/core.c b/plugins/elf/core.c
index 1e98aba..bd829af 100644
--- a/plugins/elf/core.c
+++ b/plugins/elf/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/global.h>
#include <plugins/self.h>
#include "format.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
result = add_format_elf_module_to_python_module();
#else
result = true;
diff --git a/plugins/elf/loading.h b/plugins/elf/loading.h
index e3016d4..270bb0b 100644
--- a/plugins/elf/loading.h
+++ b/plugins/elf/loading.h
@@ -26,7 +26,7 @@
#include <format/symiter.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
#include "format.h"
diff --git a/plugins/elf/python/Makefile.am b/plugins/elf/python/Makefile.am
index 29b7d98..1d4f671 100644
--- a/plugins/elf/python/Makefile.am
+++ b/plugins/elf/python/Makefile.am
@@ -1,25 +1,20 @@
noinst_LTLIBRARIES = libelfpython.la
-libelfpython_la_SOURCES = \
- constants.h constants.c \
- dynamic.h dynamic.c \
- elf_def.h elf_def.c \
- format.h format.c \
- module.h module.c \
- program.h program.c \
- section.h section.c \
+libelfpython_la_SOURCES = \
+ constants.h constants.c \
+ dynamic.h dynamic.c \
+ elf_def.h elf_def.c \
+ format.h format.c \
+ module.h module.c \
+ program.h program.c \
+ section.h section.c \
translate.h translate.c
-libelfpython_la_LDFLAGS =
+libelfpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libelfpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/elf/python/format.c b/plugins/elf/python/format.c
index e0195c4..95eaa9a 100644
--- a/plugins/elf/python/format.c
+++ b/plugins/elf/python/format.c
@@ -244,18 +244,20 @@ PyTypeObject *get_python_elf_format_type(void)
bool register_python_elf_format(PyObject *module)
{
- PyTypeObject *py_elf_format_type; /* Type Python 'ElfFormat' */
+ PyTypeObject *type; /* Type Python 'ElfFormat' */
PyObject *dict; /* Dictionnaire du module */
- py_elf_format_type = get_python_elf_format_type();
+ type = get_python_elf_format_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ELF_FORMAT,
- py_elf_format_type, get_python_executable_format_type()))
+ if (!ensure_python_executable_format_is_registered())
return false;
- if (!define_python_elf_format_constants(py_elf_format_type))
+ if (!register_class_for_pygobject(dict, G_TYPE_ELF_FORMAT, type))
+ return false;
+
+ if (!define_python_elf_format_constants(type))
return false;
return true;
diff --git a/plugins/elf/strings.h b/plugins/elf/strings.h
index 902c2f8..3a07b96 100644
--- a/plugins/elf/strings.h
+++ b/plugins/elf/strings.h
@@ -29,7 +29,7 @@
#include <glibext/delayed.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
diff --git a/plugins/elf/symbols.h b/plugins/elf/symbols.h
index f4a6eec..c736d56 100644
--- a/plugins/elf/symbols.h
+++ b/plugins/elf/symbols.h
@@ -29,7 +29,7 @@
#include <glibext/delayed.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
diff --git a/plugins/encodings/Makefile.am b/plugins/encodings/Makefile.am
new file mode 100644
index 0000000..6dd71fb
--- /dev/null
+++ b/plugins/encodings/Makefile.am
@@ -0,0 +1,64 @@
+
+lib_LTLIBRARIES = libencodings.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON_PACKAGE
+
+RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs:$$ORIGIN'
+
+else
+
+RUN_PATH = -Wl,-rpath,'$$ORIGIN'
+
+endif
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD = python/libencodingspython.la
+
+if BUILD_DISCARD_LOCAL
+
+if BUILD_PYTHON_PACKAGE
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN/..'
+else
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN'
+endif
+
+else
+
+PYTHON3_RUN_PATH = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs
+
+endif
+
+PYTHON3_LDFLAGS = $(PYTHON3_RUN_PATH) -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libencodings_la_SOURCES = \
+ base64.h base64.c \
+ core.h core.c
+
+libencodings_la_LIBADD = \
+ $(PYTHON3_LIBADD) \
+ rost/libencodingsrost.la
+
+libencodings_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+libencodings_la_LDFLAGS = \
+ -avoid-version \
+ -L$(top_srcdir)/src/.libs -lchrysacore \
+ -L$(top_srcdir)/plugins/pe/.libs -lpe \
+ $(RUN_PATH) $(PYTHON3_LDFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libencodings_la_SOURCES:%c=)
+
+
+SUBDIRS = $(PYTHON3_SUBDIRS) rost
diff --git a/plugins/encodings/base64.c b/plugins/encodings/base64.c
new file mode 100644
index 0000000..c749a87
--- /dev/null
+++ b/plugins/encodings/base64.c
@@ -0,0 +1,139 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.c - calculs d'encodages en base 64
+ *
+ * Copyright (C) 2020 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 "base64.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : input = données d'entrée à traiter. *
+* output = données sortantes constituées. [OUT] *
+* alphabet = alphabet d'encodage mis à disposition. *
+* *
+* Description : Procède à l'encodage d'un contenu en base 64. *
+* *
+* Retour : Bilan de l'opération : true en cas de réussite, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _base64_encode(const sized_binary_t *input, sized_string_t *output, const sized_string_t *alphabet)
+{
+ bool result; /* Bilan à retourner */
+ const bin_t *src; /* Tête de lecture #1 */
+ const bin_t *alpha; /* Tête de lecture #2 */
+ bin_t *iter; /* Tête d'écriture */
+ size_t i; /* Boucle de parcours */
+
+ result = (alphabet->len == 64);
+ if (!result) goto exit;
+
+ /* Création du réceptacle */
+
+ output->len = input->len * 4 / 3;
+
+ if (output->len % 4 != 0)
+ output->len += (4 - output->len % 4);
+
+ output->data = malloc((output->len + 1) * sizeof(bin_t));
+
+ /* Encodage du corps du message */
+
+ src = input->static_bin_data;
+ alpha = alphabet->static_bin_data;
+
+ iter = output->bin_data;
+
+ if (input->len > 2)
+ for (i = 0; i < (input->len - 2); i += 3)
+ {
+ *iter++ = alpha[(src[i] >> 2) & 0x3f];
+
+ *iter++ = alpha[((src[i] & 0x03) << 4) | ((src[i + 1] & 0xf0) >> 4)];
+
+ *iter++ = alpha[((src[i + 1] & 0x0f) << 2) | ((src[i + 2] & 0xc0) >> 6)];
+
+ *iter++ = alpha[src[i + 2] & 0x3f];
+
+ }
+ else
+ i = 0;
+
+ /* Bourrage final ? */
+
+ if (i < input->len)
+ {
+ *iter++ = alpha[(src[i] >> 2) & 0x3f];
+
+ if (i == (input->len - 1))
+ {
+ *iter++ = alpha[((src[i] & 0x03) << 4)];
+ *iter++ = '=';
+ }
+ else
+ {
+ *iter++ = alpha[((src[i] & 0x03) << 4) | ((src[i + 1] & 0xf0) >> 4)];
+ *iter++ = alpha[((src[i + 1] & 0x0f) << 2)];
+ }
+
+ *iter++ = '=';
+ }
+
+ *iter = 0x00;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : input = données d'entrée à traiter. *
+* output = données sortantes constituées. [OUT] *
+* *
+* Description : Procède à l'encodage par défaut d'un contenu en base 64. *
+* *
+* Retour : Bilan de l'opération : true en cas de réussite, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool base64_encode(const sized_binary_t *input, sized_string_t *output)
+{
+ bool result; /* Bilan à retourner */
+
+ const sized_string_t alphabet = {
+ .static_data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
+ .len = 64
+ };
+
+ result = _base64_encode(input, output, &alphabet);
+
+ return result;
+
+}
diff --git a/plugins/encodings/base64.h b/plugins/encodings/base64.h
new file mode 100644
index 0000000..64ddccd
--- /dev/null
+++ b/plugins/encodings/base64.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.h - prototypes pour les calculs d'encodages en base 64
+ *
+ * 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_ENCODINGS_BASE64_H
+#define _PLUGINS_ENCODINGS_BASE64_H
+
+
+#include <stdbool.h>
+
+
+#include <common/szstr.h>
+
+
+
+/* Procède à l'encodage d'un contenu en base 64. */
+bool _base64_encode(const sized_binary_t *, sized_string_t *, const sized_string_t *);
+
+/* Procède à l'encodage par défaut d'un contenu en base 64. */
+bool base64_encode(const sized_binary_t *, sized_string_t *);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_BASE64_H */
diff --git a/plugins/encodings/core.c b/plugins/encodings/core.c
new file mode 100644
index 0000000..2ece208
--- /dev/null
+++ b/plugins/encodings/core.c
@@ -0,0 +1,89 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - prototypes pour le calcul d'encodages
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <analysis/scan/core.h>
+#include <plugins/self.h>
+
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+# include "python/module.h"
+# include "python/rost/module.h"
+#endif
+#include "rost/base64.h"
+
+
+#ifdef INCLUDE_PYTHON3_BINDINGS_
+# define PG_REQ RL("PyChrysalide")
+#else
+# define PG_REQ NO_REQ
+#endif
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("Encodings", "Special encoding methods for binaries",
+ PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"),
+ PG_REQ, AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Prend acte du chargement du greffon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+ bool result; /* Bilan à retourner */
+ GScanTokenModifier *modifier; /* Modificateur à enregistrer */
+
+ modifier = g_scan_base64_modifier_new();
+
+ result = register_scan_token_modifier(modifier);
+
+ g_object_unref(G_OBJECT(modifier));
+
+ if (!result) goto exit;
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+
+ result = add_encodings_module_to_python_module();
+
+ if (result)
+ result = register_encodings_rost_modifiers();
+#endif
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/encodings/core.h b/plugins/encodings/core.h
new file mode 100644
index 0000000..75a6e73
--- /dev/null
+++ b/plugins/encodings/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour le calcul d'encodages
+ *
+ * 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_ENCODINGS_CORE_H
+#define _PLUGINS_ENCODINGS_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_CORE_H */
diff --git a/plugins/encodings/python/Makefile.am b/plugins/encodings/python/Makefile.am
new file mode 100644
index 0000000..523a6f4
--- /dev/null
+++ b/plugins/encodings/python/Makefile.am
@@ -0,0 +1,21 @@
+
+noinst_LTLIBRARIES = libencodingspython.la
+
+libencodingspython_la_SOURCES = \
+ base64.h base64.c \
+ module.h module.c
+
+libencodingspython_la_LIBADD = \
+ rost/libencodingspythonrost.la
+
+libencodingspython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) \
+ $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libencodingspython_la_SOURCES:%c=)
+
+
+SUBDIRS = rost
diff --git a/plugins/encodings/python/base64.c b/plugins/encodings/python/base64.c
new file mode 100644
index 0000000..3bc84a2
--- /dev/null
+++ b/plugins/encodings/python/base64.c
@@ -0,0 +1,139 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.c - équivalent Python du fichier "plugins/encodings/base64.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "base64.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../base64.h"
+
+
+
+/* Procède à l'encodage d'un contenu en base 64. */
+static PyObject *py_encodings_base64_encode(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = paramètre à récupérer pour le traitement. *
+* *
+* Description : Procède à l'encodage d'un contenu en base 64. *
+* *
+* Retour : None ou données sortantes constituées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_encodings_base64_encode(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Valeur à retourner */
+ sized_string_t alphabet; /* Alphabet de traitement ? */
+ Py_ssize_t alen; /* Taille de cet alphabet */
+ sized_binary_t input; /* Données à traiter */
+ Py_ssize_t ilen; /* Quantité de ces données */
+ int ret; /* Bilan de lecture des args. */
+ sized_string_t output; /* Données encodées à exporter */
+ bool status; /* Bilan de l'opération */
+
+#define ENCODINGS_BASE64_ENCODE_METHOD PYTHON_METHOD_DEF \
+( \
+ base64_encode, "input, /, alphabet=None", \
+ METH_VARARGS, py_encodings, \
+ "Encode a given content using Base64.\n" \
+ "\n" \
+ "The *input* argument has to be provided as bytes. The optional" \
+ " *alphabet* is expected to be a 64-byte array if defined.\n" \
+ "\n" \
+ "The returned value is bytes or *None* in case of error." \
+)
+
+ result = NULL;
+
+ alphabet.data = NULL;
+ alen = 0;
+
+ ret = PyArg_ParseTuple(args, "s#|s#", &input.static_data, &ilen, &alphabet.static_data, &alen);
+ if (!ret) goto exit;
+
+ alphabet.len = alen;
+ input.len = ilen;
+
+ if (alphabet.len > 0)
+ status = _base64_encode(&input, &output, &alphabet);
+ else
+ status = base64_encode(&input, &output);
+
+ if (status)
+ {
+ result = PyBytes_FromStringAndSize(output.data, output.len);
+ exit_szstr(&output);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Définit une extension du module 'encodings' à compléter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_encodings_module_with_base64(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+
+ static PyMethodDef py_base64_methods[] = {
+ ENCODINGS_BASE64_ENCODE_METHOD,
+ { NULL }
+ };
+
+ result = register_python_module_methods(super, py_base64_methods);
+
+ return result;
+
+}
diff --git a/plugins/encodings/python/base64.h b/plugins/encodings/python/base64.h
new file mode 100644
index 0000000..1e08cf6
--- /dev/null
+++ b/plugins/encodings/python/base64.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.h - équivalent Python du fichier "plugins/encodings/base64.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_ENCODINGS_PYTHON_BASE64_H
+#define _PLUGINS_ENCODINGS_PYTHON_BASE64_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'encodings' à compléter. */
+bool populate_encodings_module_with_base64(PyObject *);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_PYTHON_BASE64_H */
diff --git a/plugins/encodings/python/module.c b/plugins/encodings/python/module.c
new file mode 100644
index 0000000..454159b
--- /dev/null
+++ b/plugins/encodings/python/module.c
@@ -0,0 +1,87 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire encodings en tant que module
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "base64.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.encodings' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_encodings_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_ENCODINGS_DOC \
+ "encodings is a module providing a few implementations" \
+ " of algorithms used to encode data."
+
+ static PyModuleDef py_chrysalide_encodings_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.encodings",
+ .m_doc = PYCHRYSALIDE_PLUGINS_ENCODINGS_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins");
+
+ module = build_python_module(super, &py_chrysalide_encodings_module);
+
+ result = (module != NULL);
+
+ if (result) result = populate_encodings_module_with_base64(module);
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/encodings/python/module.h b/plugins/encodings/python/module.h
new file mode 100644
index 0000000..e7dd812
--- /dev/null
+++ b/plugins/encodings/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire encodings en tant que module
+ *
+ * Copyright (C) 2020 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_ENCODINGS_PYTHON_MODULE_H
+#define _PLUGINS_ENCODINGS_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.encodings' au module Python. */
+bool add_encodings_module_to_python_module(void);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_PYTHON_MODULE_H */
diff --git a/plugins/encodings/python/rost/Makefile.am b/plugins/encodings/python/rost/Makefile.am
new file mode 100644
index 0000000..531fb26
--- /dev/null
+++ b/plugins/encodings/python/rost/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libencodingspythonrost.la
+
+libencodingspythonrost_la_SOURCES = \
+ base64.h base64.c \
+ module.h module.c
+
+libencodingspythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) \
+ $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libencodingspythonrost_la_SOURCES:%c=)
diff --git a/plugins/encodings/python/rost/base64.c b/plugins/encodings/python/rost/base64.c
new file mode 100644
index 0000000..57bba76
--- /dev/null
+++ b/plugins/encodings/python/rost/base64.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.c - équivalent Python du fichier "plugins/encodings/rost/base64.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "base64.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/scan/patterns/modifier.h>
+
+
+#include "../../rost/base64.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_base64_modifier, G_TYPE_SCAN_BASE64_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_base64_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_base64_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_BASE64_MODIFIER_DOC \
+ "The *Base64Modifier* class transforms a byte pattern into its" \
+ " base64 encoded form.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " Base64Modifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_base64_modifier_type(void)
+{
+ static PyMethodDef py_scan_base64_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_base64_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_base64_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Base64Modifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_BASE64_MODIFIER_DOC,
+
+ .tp_methods = py_scan_base64_modifier_methods,
+ .tp_getset = py_scan_base64_modifier_getseters,
+
+ .tp_init = py_scan_base64_modifier_init,
+ .tp_new = py_scan_base64_modifier_new,
+
+ };
+
+ return &py_scan_base64_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....Base64Modifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_base64_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python Base64Modifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_base64_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_BASE64_MODIFIER, 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 transformation par encodage en Base64. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_base64_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_base64_modifier_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 Base64 modifier");
+ break;
+
+ case 1:
+ *((GScanBase64Modifier **)dst) = G_SCAN_BASE64_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/encodings/python/rost/base64.h b/plugins/encodings/python/rost/base64.h
new file mode 100644
index 0000000..0ef0834
--- /dev/null
+++ b/plugins/encodings/python/rost/base64.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.h - équivalent Python du fichier "plugins/encodings/rost/base64.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H
+#define _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_base64_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Base64Modifier'. */
+bool ensure_python_scan_base64_modifier_is_registered(void);
+
+/* Tente de convertir en transformation par encodage en Base64. */
+int convert_to_scan_base64_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H */
diff --git a/plugins/encodings/python/rost/module.c b/plugins/encodings/python/rost/module.c
new file mode 100644
index 0000000..4812bb5
--- /dev/null
+++ b/plugins/encodings/python/rost/module.c
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire rost en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "base64.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les modificateurs pour ROST. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_encodings_rost_modifiers(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_base64_modifier_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/encodings/python/rost/module.h b/plugins/encodings/python/rost/module.h
new file mode 100644
index 0000000..ba021cb
--- /dev/null
+++ b/plugins/encodings/python/rost/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire rost en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_ENCODINGS_PYTHON_ROST_MODULE_H
+#define _PLUGINS_ENCODINGS_PYTHON_ROST_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Intègre les modificateurs pour ROST. */
+bool register_encodings_rost_modifiers(void);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_PYTHON_ROST_MODULE_H */
diff --git a/plugins/encodings/rost/Makefile.am b/plugins/encodings/rost/Makefile.am
new file mode 100644
index 0000000..efca690
--- /dev/null
+++ b/plugins/encodings/rost/Makefile.am
@@ -0,0 +1,12 @@
+
+noinst_LTLIBRARIES = libencodingsrost.la
+
+libencodingsrost_la_SOURCES = \
+ base64.h base64.c
+
+libencodingsrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libencodingsrost_la_SOURCES:%c=)
diff --git a/plugins/encodings/rost/base64.c b/plugins/encodings/rost/base64.c
new file mode 100644
index 0000000..adbb2fb
--- /dev/null
+++ b/plugins/encodings/rost/base64.c
@@ -0,0 +1,555 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.c - transormation en encodage Base64
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "base64.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+#include "../base64.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions en encodage Base64. */
+static void g_scan_base64_modifier_class_init(GScanBase64ModifierClass *klass);
+
+/* Initialise une instance de transmission en encodage Base64. */
+static void g_scan_base64_modifier_init(GScanBase64Modifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_base64_modifier_dispose(GScanBase64Modifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_base64_modifier_finalize(GScanBase64Modifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_base64_modifier_get_name(const GScanBase64Modifier *);
+
+/* Finalise l'encoddage en Base64 d'un motif transformé. */
+static void strip_base64_modifier_output(const sized_binary_t *, const sized_binary_t *, size_t, sized_binary_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_base64_modifier_transform(const GScanBase64Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *);
+
+/* Détermine si un argument est bien toléré par un modificateur. */
+static bool g_scan_base64_modifier_can_handle_arg(const GScanBase64Modifier *, const modifier_arg_t *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_base64_modifier_transform_with_arg(const GScanBase64Modifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *);
+
+/* Retrouve l'origine d'une correspondance à partir d'un indice. */
+static char *g_scan_base64_modifier_get_path(const GScanBase64Modifier *, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation en encodage Base64. */
+G_DEFINE_TYPE(GScanBase64Modifier, g_scan_base64_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions en encodage Base64. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_base64_modifier_class_init(GScanBase64ModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_base64_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_base64_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_base64_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_base64_modifier_transform;
+ modifier->can_handle = (can_token_modifier_handle_arg)g_scan_base64_modifier_can_handle_arg;
+ modifier->transform_with = (transform_scan_token_with_fc)g_scan_base64_modifier_transform_with_arg;
+ modifier->get_path = (get_modifier_path)g_scan_base64_modifier_get_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission en encodage Base64. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_base64_modifier_init(GScanBase64Modifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_base64_modifier_dispose(GScanBase64Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_base64_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_base64_modifier_finalize(GScanBase64Modifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_base64_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des encodages en Base64. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_base64_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_BASE64_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_base64_modifier_get_name(const GScanBase64Modifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("base64");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : input = contenu brut d'origine. *
+* tmpput = encodage en Base64 intermédiaire obtenu. *
+* skip = nombre de caractères initiaux à sauter. *
+* output = encodage en Base64 final à conserver. *
+* *
+* Description : Finalise l'encoddage en Base64 d'un motif transformé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void strip_base64_modifier_output(const sized_binary_t *input, const sized_binary_t *tmpput, size_t skip, sized_binary_t *output)
+{
+ size_t keep; /* Nombre d'octets immuables */
+
+ keep = (input->len * 8) / 6;
+
+ assert(keep >= skip);
+
+ if (skip > 0)
+ skip++;
+
+ keep -= skip;
+
+ output->len = keep;
+ output->bin_data = malloc(keep * sizeof(bin_t));
+
+ memcpy(output->bin_data, tmpput->static_bin_data + skip, keep);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_base64_modifier_transform(const GScanBase64Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ sized_binary_t tmp_in; /* Manipulation des variations */
+ sized_binary_t tmp_out; /* Manipulation des variations */
+
+ result = true;
+
+ *dcount = scount * 3;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount && result; i++)
+ {
+ _src = src + i;
+
+ tmp_in.data = malloc((_src->len + 2) * sizeof(bin_t));
+
+ /**
+ * Explications sur la définition des modifications sur les
+ * encodages produits : https://www.leeholmes.com/searching-for-content-in-base-64-strings/
+ */
+
+ /* Encodage premier */
+
+ result = base64_encode(_src, &tmp_out);
+ if (!result) goto exit;
+
+ strip_base64_modifier_output(_src, &tmp_out, 0, binary++);
+
+ exit_szstr(&tmp_out);
+
+ /* Variante 1 */
+
+ tmp_in.data[0] = ' ';
+ memcpy(&tmp_in.data[1], _src->static_bin_data, _src->len);
+
+ tmp_in.len = _src->len + 1;
+
+ result = base64_encode(&tmp_in, &tmp_out);
+ if (!result) goto exit;
+
+ strip_base64_modifier_output(&tmp_in, &tmp_out, 1, binary);
+
+ /**
+ * Lors qu'un unique octet est encodé, cet octet ne produit aucun
+ * caractère que ne dépend que de lui :
+ *
+ * | X |
+ * 1 2 3 4 5 6 | 7 8 1 2 3 4 | 5 6 7 8 1 2 | 3 4 5 6 7 8
+ *
+ * Les compteurs sont alors diminués.
+ */
+
+ if (binary->len == 0)
+ (*dcount)--;
+ else
+ binary++;
+
+ exit_szstr(&tmp_out);
+
+ /* Variante 2 */
+
+ tmp_in.data[0] = ' ';
+ tmp_in.data[2] = ' ';
+ memcpy(&tmp_in.data[2], _src->static_bin_data, _src->len);
+
+ tmp_in.len = _src->len + 2;
+
+ result = base64_encode(&tmp_in, &tmp_out);
+ if (!result) goto exit;
+
+ strip_base64_modifier_output(&tmp_in, &tmp_out, 2, binary++);
+
+ exit_szstr(&tmp_out);
+
+ exit:
+
+ exit_szstr(&tmp_in);
+
+ }
+
+ if (!result)
+ {
+ for (i = 0; i < *dcount; i++)
+ exit_szstr(&(*dest)[i]);
+
+ free(*dest);
+
+ *dcount = 0;
+ *dest = NULL;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* arg = argument de personnalisation. *
+* *
+* Description : Détermine si un argument est bien toléré par un modificateur.*
+* *
+* Retour : Bilan de la consultation : support ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_base64_modifier_can_handle_arg(const GScanBase64Modifier *modifier, const modifier_arg_t *arg)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+
+ switch (arg->type)
+ {
+ case MAT_STRING:
+ result = (arg->value.string.len == 64);
+ break;
+
+ default:
+ result = false;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquences d'octets à traiter. *
+* scount = quantité de ces séquences. *
+* arg = argument de personnalisation. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* dcount = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_base64_modifier_transform_with_arg(const GScanBase64Modifier *modifier, const sized_binary_t *src, size_t scount, const modifier_arg_t *arg, sized_binary_t **dest, size_t *dcount)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ const sized_binary_t *_src; /* Source courante */
+ sized_binary_t tmp_in; /* Manipulation des variations */
+ sized_binary_t tmp_out; /* Manipulation des variations */
+
+ result = (arg->type == MAT_STRING);
+ if (!result) goto bad_arg;
+
+ *dcount = scount * 3;
+ *dest = calloc(*dcount, sizeof(sized_binary_t));
+
+ binary = &(*dest)[0];
+
+ for (i = 0; i < scount && result; i++)
+ {
+ _src = src + i;
+
+ tmp_in.data = malloc((_src->len + 2) * sizeof(bin_t));
+
+ /**
+ * Explications sur la définition des modifications sur les
+ * encodages produits : https://www.leeholmes.com/searching-for-content-in-base-64-strings/
+ */
+
+ /* Encodage premier */
+
+ result = _base64_encode(_src, &tmp_out, &arg->value.string);
+ if (!result) goto exit;
+
+ strip_base64_modifier_output(_src, &tmp_out, 0, binary++);
+
+ exit_szstr(&tmp_out);
+
+ /* Variante 1 */
+
+ tmp_in.data[0] = ' ';
+ memcpy(&tmp_in.data[1], _src->static_bin_data, _src->len);
+
+ tmp_in.len = _src->len + 1;
+
+ result = _base64_encode(&tmp_in, &tmp_out, &arg->value.string);
+ if (!result) goto exit;
+
+ strip_base64_modifier_output(&tmp_in, &tmp_out, 1, binary++);
+
+ exit_szstr(&tmp_out);
+
+ /* Variante 2 */
+
+ tmp_in.data[0] = ' ';
+ tmp_in.data[2] = ' ';
+ memcpy(&tmp_in.data[2], _src->static_bin_data, _src->len);
+
+ tmp_in.len = _src->len + 2;
+
+ result = _base64_encode(&tmp_in, &tmp_out, &arg->value.string);
+ if (!result) goto exit;
+
+ strip_base64_modifier_output(&tmp_in, &tmp_out, 2, binary++);
+
+ exit_szstr(&tmp_out);
+
+ exit:
+
+ exit_szstr(&tmp_in);
+
+ }
+
+ if (!result)
+ {
+ for (i = 0; i < *dcount; i++)
+ exit_szstr(&(*dest)[i]);
+
+ free(*dest);
+
+ *dcount = 0;
+ *dest = NULL;
+
+ }
+
+ bad_arg:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* index = indice de la combinaison ciblée. [OUT] *
+* *
+* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
+* *
+* Retour : Version humainement lisible de la combinaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_base64_modifier_get_path(const GScanBase64Modifier *modifier, size_t *index)
+{
+ char *result; /* Combinaison à retourner */
+
+ if (*index > 3)
+ {
+ result = NULL;
+ (*index) -= 3;
+ }
+
+ else
+ result = strdup("base64");
+
+ return result;
+
+}
diff --git a/plugins/encodings/rost/base64.h b/plugins/encodings/rost/base64.h
new file mode 100644
index 0000000..646b945
--- /dev/null
+++ b/plugins/encodings/rost/base64.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * base64.h - prototypes pour la transormation en encodage Base64
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ENCODINGS_ROST_BASE64_H
+#define _PLUGINS_ENCODINGS_ROST_BASE64_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/scan/patterns/modifier.h>
+
+
+
+#define G_TYPE_SCAN_BASE64_MODIFIER g_scan_base64_modifier_get_type()
+#define G_SCAN_BASE64_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BASE64_MODIFIER, GScanBase64Modifier))
+#define G_IS_SCAN_BASE64_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BASE64_MODIFIER))
+#define G_SCAN_BASE64_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BASE64_MODIFIER, GScanBase64ModifierClass))
+#define G_IS_SCAN_BASE64_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BASE64_MODIFIER))
+#define G_SCAN_BASE64_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BASE64_MODIFIER, GScanBase64ModifierClass))
+
+
+/* Transormation en encodage Base64 (instance) */
+typedef GScanTokenModifier GScanBase64Modifier;
+
+/* Transormation en encodage Base64 (classe) */
+typedef GScanTokenModifierClass GScanBase64ModifierClass;
+
+
+/* Indique le type défini pour une transormation en encodage Base64. */
+GType g_scan_base64_modifier_get_type(void);
+
+/* Construit un modificateur livrant des encodages en Base64. */
+GScanTokenModifier *g_scan_base64_modifier_new(void);
+
+
+
+#endif /* _PLUGINS_ENCODINGS_ROST_BASE64_H */
diff --git a/plugins/fmtp/Makefile.am b/plugins/fmtp/Makefile.am
index f365c03..388adf3 100644
--- a/plugins/fmtp/Makefile.am
+++ b/plugins/fmtp/Makefile.am
@@ -11,10 +11,12 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs'
endif
-libfmtp_la_SOURCES = \
- def.h \
+libfmtp_la_SOURCES = \
+ def.h \
parser.h parser.c
+libfmtp_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libfmtp_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -24,8 +26,3 @@ libfmtp_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libfmtp_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/gdbrsp/python/gdb.c b/plugins/gdbrsp/python/gdb.c
index 24d9717..15c9f94 100644
--- a/plugins/gdbrsp/python/gdb.c
+++ b/plugins/gdbrsp/python/gdb.c
@@ -163,7 +163,10 @@ bool ensure_python_gdb_debugger_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_GDB_DEBUGGER, type, get_python_binary_debugger_type()))
+ if (!ensure_python_binary_debugger_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_GDB_DEBUGGER, type))
return false;
}
diff --git a/plugins/itanium/Makefile.am b/plugins/itanium/Makefile.am
index e1b2d9e..eee0da4 100644
--- a/plugins/itanium/Makefile.am
+++ b/plugins/itanium/Makefile.am
@@ -35,17 +35,19 @@ PYTHON3_SUBDIRS = python
endif
-libitanium_la_SOURCES = \
- abi.h abi.c \
- component-int.h \
- component.h component.c \
- context.h context.c \
- core.h core.c \
+libitanium_la_SOURCES = \
+ abi.h abi.c \
+ component-int.h \
+ component.h component.c \
+ context.h context.c \
+ core.h core.c \
demangler.h demangler.c
-libitanium_la_LIBADD = \
+libitanium_la_LIBADD = \
$(PYTHON3_LIBADD)
+libitanium_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libitanium_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -57,8 +59,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libitanium_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/itanium/core.c b/plugins/itanium/core.c
index 6bf67c1..3f3feb0 100644
--- a/plugins/itanium/core.c
+++ b/plugins/itanium/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/demanglers.h>
#include <plugins/self.h>
#include "demangler.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,9 +64,9 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
- result = register_demangler_type("itanium", G_TYPE_ITANIUM_DEMANGLER);
+ result = register_demangler_type(G_TYPE_ITANIUM_DEMANGLER);
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_mangling_itanium_module_to_python_module();
#endif
diff --git a/plugins/itanium/demangler.c b/plugins/itanium/demangler.c
index 5fe0d09..fc445f5 100644
--- a/plugins/itanium/demangler.c
+++ b/plugins/itanium/demangler.c
@@ -58,6 +58,9 @@ static void g_itanium_demangler_dispose(GItaniumDemangler *);
/* Procède à la libération totale de la mémoire. */
static void g_itanium_demangler_finalize(GItaniumDemangler *);
+/* Fournit la désignation interne du décodeur de désignations. */
+static char *g_itanium_demangler_get_key(const GItaniumDemangler *);
+
/* Indique le type défini pour un décodeur de désignations. */
@@ -88,6 +91,7 @@ static void g_itanium_demangler_class_init(GItaniumDemanglerClass *klass)
demangler = G_COMP_DEMANGLER_CLASS(klass);
+ demangler->get_key = (get_demangler_key_fc)g_itanium_demangler_get_key;
demangler->can_demangle = (can_be_demangled_fc)NULL;
demangler->ns_sep = "::";
@@ -173,3 +177,26 @@ GCompDemangler *g_itanium_demangler_new(void)
return G_COMP_DEMANGLER(result);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = décodeur à consulter. *
+* *
+* Description : Fournit la désignation interne du décodeur de désignations. *
+* *
+* Retour : Simple chaîne de caractères. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_itanium_demangler_get_key(const GItaniumDemangler *demangler)
+{
+ char *result; /* Désignation à renvoyer */
+
+ result = strdup("itanium");
+
+ return result;
+
+}
diff --git a/plugins/itanium/python/Makefile.am b/plugins/itanium/python/Makefile.am
index b0a3da1..a00bda8 100644
--- a/plugins/itanium/python/Makefile.am
+++ b/plugins/itanium/python/Makefile.am
@@ -1,19 +1,14 @@
noinst_LTLIBRARIES = libitaniumpython.la
-libitaniumpython_la_SOURCES = \
- demangler.h demangler.c \
+libitaniumpython_la_SOURCES = \
+ demangler.h demangler.c \
module.h module.c
-libitaniumpython_la_LDFLAGS =
+libitaniumpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libitaniumpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/itanium/python/demangler.c b/plugins/itanium/python/demangler.c
index 5819ac4..12cc6c5 100644
--- a/plugins/itanium/python/demangler.c
+++ b/plugins/itanium/python/demangler.c
@@ -140,15 +140,17 @@ PyTypeObject *get_python_itanium_demangler_type(void)
bool register_python_itanium_demangler(PyObject *module)
{
- PyTypeObject *py_itanium_demangler_type;/* Type 'ItaniumDemangler' */
+ PyTypeObject *type; /* Type 'ItaniumDemangler' */
PyObject *dict; /* Dictionnaire du module */
- py_itanium_demangler_type = get_python_itanium_demangler_type();
+ type = get_python_itanium_demangler_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ITANIUM_DEMANGLER,
- py_itanium_demangler_type, get_python_compiler_demangler_type()))
+ if (!ensure_python_compiler_demangler_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ITANIUM_DEMANGLER, type))
return false;
return true;
diff --git a/plugins/java/Makefile.am b/plugins/java/Makefile.am
index 0e40bfa..cd94927 100644
--- a/plugins/java/Makefile.am
+++ b/plugins/java/Makefile.am
@@ -16,14 +16,9 @@ libformatjava_la_SOURCES = \
# method.h method.c \
# pool.h pool.c
-libformatjava_la_LDFLAGS =
+libformatjava_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=%)
dev_HEADERS = $(libformatjava_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/javadesc/Makefile.am b/plugins/javadesc/Makefile.am
index 7a79b99..8f91010 100644
--- a/plugins/javadesc/Makefile.am
+++ b/plugins/javadesc/Makefile.am
@@ -35,16 +35,18 @@ PYTHON3_SUBDIRS = python
endif
-libjavadesc_la_SOURCES = \
- context.h context.c \
- core.h core.c \
- demangler.h demangler.c \
- field.h field.c \
+libjavadesc_la_SOURCES = \
+ context.h context.c \
+ core.h core.c \
+ demangler.h demangler.c \
+ field.h field.c \
method.h method.c
-libjavadesc_la_LIBADD = \
+libjavadesc_la_LIBADD = \
$(PYTHON3_LIBADD)
+libjavadesc_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libjavadesc_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -56,8 +58,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libjavadesc_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/javadesc/core.c b/plugins/javadesc/core.c
index bda0f56..420d9f5 100644
--- a/plugins/javadesc/core.c
+++ b/plugins/javadesc/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/demanglers.h>
#include <plugins/self.h>
#include "demangler.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,9 +64,9 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
- result = register_demangler_type("java", G_TYPE_JAVA_DEMANGLER);
+ result = register_demangler_type(G_TYPE_JAVA_DEMANGLER);
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_mangling_javadesc_module_to_python_module();
#endif
diff --git a/plugins/javadesc/demangler.c b/plugins/javadesc/demangler.c
index 78b62f1..eaacacf 100644
--- a/plugins/javadesc/demangler.c
+++ b/plugins/javadesc/demangler.c
@@ -58,6 +58,9 @@ static void g_java_demangler_dispose(GJavaDemangler *);
/* Procède à la libération totale de la mémoire. */
static void g_java_demangler_finalize(GJavaDemangler *);
+/* Fournit la désignation interne du décodeur de désignations. */
+static char *g_java_demangler_get_key(const GJavaDemangler *);
+
/* Indique le type défini pour un décodeur de désignations. */
@@ -88,6 +91,7 @@ static void g_java_demangler_class_init(GJavaDemanglerClass *klass)
demangler = G_COMP_DEMANGLER_CLASS(klass);
+ demangler->get_key = (get_demangler_key_fc)g_java_demangler_get_key;
demangler->can_demangle = (can_be_demangled_fc)NULL;
demangler->ns_sep = ".";
@@ -173,3 +177,26 @@ GCompDemangler *g_java_demangler_new(void)
return G_COMP_DEMANGLER(result);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = décodeur à consulter. *
+* *
+* Description : Fournit la désignation interne du décodeur de désignations. *
+* *
+* Retour : Simple chaîne de caractères. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_java_demangler_get_key(const GJavaDemangler *demangler)
+{
+ char *result; /* Désignation à renvoyer */
+
+ result = strdup("java");
+
+ return result;
+
+}
diff --git a/plugins/javadesc/python/Makefile.am b/plugins/javadesc/python/Makefile.am
index aa7deeb..2b1a8eb 100644
--- a/plugins/javadesc/python/Makefile.am
+++ b/plugins/javadesc/python/Makefile.am
@@ -1,19 +1,14 @@
noinst_LTLIBRARIES = libjavadescpython.la
-libjavadescpython_la_SOURCES = \
- demangler.h demangler.c \
+libjavadescpython_la_SOURCES = \
+ demangler.h demangler.c \
module.h module.c
-libjavadescpython_la_LDFLAGS =
+libjavadescpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libjavadescpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/javadesc/python/demangler.c b/plugins/javadesc/python/demangler.c
index 3a972cee..62b24c7 100644
--- a/plugins/javadesc/python/demangler.c
+++ b/plugins/javadesc/python/demangler.c
@@ -142,15 +142,17 @@ PyTypeObject *get_python_java_demangler_type(void)
bool register_python_java_demangler(PyObject *module)
{
- PyTypeObject *py_java_demangler_type; /* Type Python 'JavaDemangler' */
+ PyTypeObject *type; /* Type Python 'JavaDemangler' */
PyObject *dict; /* Dictionnaire du module */
- py_java_demangler_type = get_python_java_demangler_type();
+ type = get_python_java_demangler_type();
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_JAVA_DEMANGLER,
- py_java_demangler_type, get_python_compiler_demangler_type()))
+ if (!ensure_python_compiler_demangler_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_JAVA_DEMANGLER, type))
return false;
return true;
diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am
new file mode 100644
index 0000000..9a4e112
--- /dev/null
+++ b/plugins/kaitai/Makefile.am
@@ -0,0 +1,93 @@
+
+BUILT_SOURCES = grammar.h
+
+
+# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS
+# afin de conserver des noms de fichiers simples, ie sans le nom de la
+# bibliothèque de sortie en préfixe.
+
+AM_YFLAGS = -v -d -p kaitai_ -Wno-yacc -Wcounterexamples
+
+AM_LFLAGS = -P kaitai_ -o lex.yy.c --header-file=tokens.h \
+ -Dyyget_lineno=kaitai_get_lineno \
+ -Dyy_scan_bytes=kaitai__scan_bytes \
+ -Dyy_delete_buffer=kaitai__delete_buffer
+
+lib_LTLIBRARIES = libkaitai.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON_PACKAGE
+
+RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs'
+
+endif
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD = python/libkaitaipython.la
+
+if BUILD_DISCARD_LOCAL
+
+if BUILD_PYTHON_PACKAGE
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN/..'
+else
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN'
+endif
+
+else
+
+PYTHON3_RUN_PATH = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs
+
+endif
+
+PYTHON3_LDFLAGS = $(PYTHON3_RUN_PATH) -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libkaitai_la_SOURCES = \
+ array-int.h \
+ array.h array.c \
+ core.h core.c \
+ expression.h \
+ import.h import.c \
+ parser-int.h \
+ parser.h parser.c \
+ record-int.h \
+ record.h record.c \
+ scope.h scope.c \
+ stream-int.h \
+ stream.h stream.c \
+ tokens.l \
+ grammar.y
+
+libkaitai_la_LIBADD = \
+ parsers/libkaitaiparsers.la \
+ records/libkaitairecords.la \
+ rost/libkaitairost.la \
+ $(PYTHON3_LIBADD)
+
+libkaitai_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+libkaitai_la_LDFLAGS = \
+ -L$(top_srcdir)/src/.libs -lchrysacore \
+ $(PYTHON3_LDFLAGS)
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitai_la_SOURCES:%c=)
+
+
+# Automake fait les choses à moitié
+CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
+
+# Pareil : de tous les fichiers générés, seule la sortie de Flex saute pour les distributions !
+EXTRA_DIST = tokens.h
+
+
+SUBDIRS = parsers records rost $(PYTHON3_SUBDIRS)
diff --git a/plugins/kaitai/array-int.h b/plugins/kaitai/array-int.h
new file mode 100644
index 0000000..123b16d
--- /dev/null
+++ b/plugins/kaitai/array-int.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array-int.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_ARRAY_INT_H
+#define PLUGINS_KAITAI_ARRAY_INT_H
+
+
+#include "array.h"
+
+
+
+/* Tableau rassemblant des éléments divers (instance) */
+struct _GKaitaiArray
+{
+ GObject parent; /* A laisser en premier */
+
+ resolved_value_t *items; /* Eléments du tableau */
+ size_t count; /* Quantité de ces éléments */
+
+};
+
+/* Tableau rassemblant des éléments divers (classe) */
+struct _GKaitaiArrayClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* PLUGINS_KAITAI_ARRAY_INT_H */
diff --git a/plugins/kaitai/array.c b/plugins/kaitai/array.c
new file mode 100644
index 0000000..86f0856
--- /dev/null
+++ b/plugins/kaitai/array.c
@@ -0,0 +1,376 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.c - données associées à un flux de données Kaitai
+ *
+ * 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 "array.h"
+
+
+#include <assert.h>
+#include <limits.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "array-int.h"
+#include "expression.h"
+
+
+
+/* Initialise la classe des flux de données pour Kaitai. */
+static void g_kaitai_array_class_init(GKaitaiArrayClass *);
+
+/* Initialise un flux de données accessibles à Kaitai. */
+static void g_kaitai_array_init(GKaitaiArray *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_array_dispose(GKaitaiArray *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_array_finalize(GKaitaiArray *);
+
+/* Détermine la taille de la séquence d'octets du tableau. */
+static bool g_kaitai_array_compute_bytes_length(const GKaitaiArray *, size_t *);
+
+
+
+/* Indique le type défini pour un tableau rassemblant des éléments Kaitai. */
+G_DEFINE_TYPE(GKaitaiArray, g_kaitai_array, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des tableau d'éléments Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_array_class_init(GKaitaiArrayClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_array_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_array_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = instance à initialiser. *
+* *
+* Description : Initialise un tableau rassemblant des éléments divers. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_array_init(GKaitaiArray *array)
+{
+ array->items = NULL;
+ array->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_array_dispose(GKaitaiArray *array)
+{
+ G_OBJECT_CLASS(g_kaitai_array_parent_class)->dispose(G_OBJECT(array));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_array_finalize(GKaitaiArray *array)
+{
+ G_OBJECT_CLASS(g_kaitai_array_parent_class)->finalize(G_OBJECT(array));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une amorce de tableau pour rassembler des éléments.*
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiArray *g_kaitai_array_new(void)
+{
+ GKaitaiArray *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_ARRAY, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = tableau Kaitai à consulter. *
+* *
+* Description : Dénombre le nombre d'éléments enregistrés. *
+* *
+* Retour : Taille du tableau manipulé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_kaitai_array_count_items(const GKaitaiArray *array)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = array->count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = tableau Kaitai à compléter. *
+* item = élément Kaitai à archiver. *
+* *
+* Description : Intègre un élément supplémentaire dans un tableau Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_kaitai_array_append_item(GKaitaiArray *array, const resolved_value_t *item)
+{
+ array->items = realloc(array->items, ++array->count * sizeof(resolved_value_t));
+
+ COPY_RESOLVED_VALUE(array->items[array->count - 1], *item);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de correspondances attribut/binaire. *
+* index = indice de la correspondance visée. *
+* item = élément archivé dans le talbeau à fournir. [OUT] *
+* *
+* Description : Fournit un élément ciblé dans un tableau Kaitai. *
+* *
+* Retour : Validité de l'emplacmeent pour élément à renseigner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_array_get_item(const GKaitaiArray *array, size_t index, resolved_value_t *item)
+{
+ bool result; /* Bilan à retourner */
+
+ result = (index < array->count);
+
+ if (result)
+ COPY_RESOLVED_VALUE(*item, array->items[index]);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = tableau Kaitai à consulter. *
+* length = nombre d'octets représentés. [OUT] *
+* *
+* Description : Détermine la taille de la séquence d'octets du tableau. *
+* *
+* Retour : true si le tableau peut être converti en octets, ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_array_compute_bytes_length(const GKaitaiArray *array, size_t *length)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ const resolved_value_t *item; /* Elément en cours d'analyse */
+ size_t extra; /* Taille d'un sous-tableau */
+
+ result = true;
+
+ *length = 0;
+
+ for (i = 0; i < array->count && result; i++)
+ {
+ item = &array->items[i];
+
+ switch (item->type)
+ {
+ case GVT_UNSIGNED_INTEGER:
+ result = (item->unsigned_integer <= UCHAR_MAX);
+ if (result) (*length)++;
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ result = (0 <= item->signed_integer && item->signed_integer <= SCHAR_MAX);
+ if (result) (*length)++;
+ break;
+
+ case GVT_BYTES:
+ *length += item->bytes.len;
+ break;
+
+ case GVT_ARRAY:
+ result = g_kaitai_array_compute_bytes_length(item->array, &extra);
+ if (result) *length += extra;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : array = tableau Kaitai à consulter. *
+* bytes = conversion en série d'octets équivalent. [OUT] *
+* *
+* Description : Convertit un tableau d'éléments en séquence d'octets. *
+* *
+* Retour : true si une série d'octets a pu être constituée, ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_array_convert_to_bytes(const GKaitaiArray *array, sized_string_t *bytes)
+{
+ bool result; /* Bilan à retourner */
+ size_t length; /* Taille de la chaîne finale */
+ size_t i; /* Boucle de parcours */
+ const resolved_value_t *item; /* Elément en cours d'analyse */
+ char *iter; /* Tête d'écriture */
+ sized_string_t extra; /* Données d'un sous-tableau */
+
+ /* Détermination de la taille finale */
+
+ result = g_kaitai_array_compute_bytes_length(array, &length);
+
+ /* Construction d'une chaîne d'octets si possible */
+
+ if (result)
+ {
+ bytes->data = malloc(length * sizeof(char));
+ bytes->len = length;
+
+ iter = bytes->data;
+
+ for (i = 0; i < array->count; i++)
+ {
+ item = &array->items[i];
+
+ switch (item->type)
+ {
+ case GVT_UNSIGNED_INTEGER:
+ *iter = item->unsigned_integer;
+ iter++;
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ *iter = item->signed_integer;
+ iter++;
+ break;
+
+ case GVT_BYTES:
+ memcpy(iter, item->bytes.data, item->bytes.len);
+ iter += item->bytes.len;
+ break;
+
+ case GVT_ARRAY:
+ result = g_kaitai_array_convert_to_bytes(item->array, &extra);
+ assert(result);
+
+ memcpy(iter, extra.data, extra.len);
+ iter += extra.len;
+
+ exit_szstr(&extra);
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/array.h b/plugins/kaitai/array.h
new file mode 100644
index 0000000..e93c7c0
--- /dev/null
+++ b/plugins/kaitai/array.h
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_ARRAY_H
+#define PLUGINS_KAITAI_ARRAY_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <common/szstr.h>
+
+
+
+/* expression.h : informations transportées par une expression */
+typedef struct _resolved_value_t resolved_value_t;
+
+
+
+#define G_TYPE_KAITAI_ARRAY g_kaitai_array_get_type()
+#define G_KAITAI_ARRAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_ARRAY, GKaitaiArray))
+#define G_IS_KAITAI_ARRAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_ARRAY))
+#define G_KAITAI_ARRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_ARRAY, GKaitaiArrayClass))
+#define G_IS_KAITAI_ARRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_ARRAY))
+#define G_KAITAI_ARRAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_ARRAY, GKaitaiArrayClass))
+
+
+/* Tableau rassemblant des éléments divers (instance) */
+typedef struct _GKaitaiArray GKaitaiArray;
+
+/* Tableau rassemblant des éléments divers (classe) */
+typedef struct _GKaitaiArrayClass GKaitaiArrayClass;
+
+
+/* Indique le type défini pour un tableau rassemblant des éléments Kaitai. */
+GType g_kaitai_array_get_type(void);
+
+/* Constitue une amorce de tableau pour rassembler des éléments. */
+GKaitaiArray *g_kaitai_array_new(void);
+
+/* Dénombre le nombre d'éléments enregistrés. */
+size_t g_kaitai_array_count_items(const GKaitaiArray *);
+
+/* Intègre un élément supplémentaire dans un tableau Kaitai. */
+void g_kaitai_array_append_item(GKaitaiArray *, const resolved_value_t *);
+
+/* Fournit un élément ciblé dans un tableau Kaitai. */
+bool g_kaitai_array_get_item(const GKaitaiArray *, size_t, resolved_value_t *);
+
+/* Convertit un tableau d'éléments en séquence d'octets. */
+bool g_kaitai_array_convert_to_bytes(const GKaitaiArray *, sized_string_t *);
+
+
+
+#endif /* PLUGINS_KAITAI_ARRAY_H */
diff --git a/plugins/kaitai/core.c b/plugins/kaitai/core.c
new file mode 100644
index 0000000..c41d96d
--- /dev/null
+++ b/plugins/kaitai/core.c
@@ -0,0 +1,81 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - prise en charge des descriptions de binaires au format Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <plugins/self.h>
+
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+# include "python/module.h"
+#endif
+#include "rost/core.h"
+
+
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+# define PG_REQ RL("PyChrysalide")
+#else
+# define PG_REQ NO_REQ
+#endif
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("Kaitai", "Content parser using Kaitai structure definitions",
+ PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/kaitai"),
+ PG_REQ, AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Prend acte du chargement du greffon. *
+* *
+* Retour : Bilan du chargement mené. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+ bool result; /* Bilan à retourner */
+
+ result = add_kaitai_support_to_rost();
+
+#ifdef INCLUDE_PYTHON3_BINDINGS
+
+ if (result)
+ result = add_kaitai_module_to_python_module();
+
+ if (result)
+ result = populate_kaitai_module();
+
+#endif
+
+ return result;
+
+}
diff --git a/plugins/kaitai/core.h b/plugins/kaitai/core.h
new file mode 100644
index 0000000..61241f4
--- /dev/null
+++ b/plugins/kaitai/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour la prise en charge des descriptions de binaires au format Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_CORE_H
+#define _PLUGINS_KAITAI_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif /* _PLUGINS_KAITAI_CORE_H */
diff --git a/plugins/kaitai/expression.h b/plugins/kaitai/expression.h
new file mode 100644
index 0000000..06cf9cf
--- /dev/null
+++ b/plugins/kaitai/expression.h
@@ -0,0 +1,134 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expression.h - déclarations de prototypes utiles aux résolutions d'expressions
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_EXPRESSION_H
+#define _PLUGINS_KAITAI_EXPRESSION_H
+
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+
+#include <common/szstr.h>
+
+
+#include "array.h"
+#include "scope.h"
+#include "stream.h"
+
+
+
+/* Type de valeur résolue */
+typedef enum _GrammarValueType
+{
+ GVT_ERROR, /* Erreur remontée */
+ GVT_UNSIGNED_INTEGER, /* Valeur entière #1 */
+ GVT_SIGNED_INTEGER, /* Valeur entière #2 */
+ GVT_FLOAT, /* Valeur fractionnée */
+ GVT_BOOLEAN, /* Valeur booléenne */
+ GVT_BYTES, /* Série d'octets dynamique */
+ GVT_ARRAY, /* Tableau d'éléments divers */
+ GVT_RECORD, /* Correspondance en place */
+ GVT_STREAM, /* Flux de données */
+
+} GrammarValueType;
+
+/* Informations transportées par une expression */
+typedef struct _resolved_value_t
+{
+ GrammarValueType type; /* Type de valeur portée */
+
+ union
+ {
+ unsigned long long unsigned_integer;/* Valeur entière #1 */
+ signed long long signed_integer; /* Valeur entière #2 */
+ double floating_number; /* Valeur à virgule flottante */
+ bool status; /* Valeur à deux états */
+ sized_string_t bytes; /* Série d'octets */
+
+ GKaitaiArray *array; /* Tableau d'éléments divers */
+ GMatchRecord *record; /* Correspondance désignée */
+ GKaitaiStream *stream; /* Flux de données pour Kaitai */
+
+ };
+
+} resolved_value_t;
+
+
+#define COPY_RESOLVED_VALUE(dst, src) \
+ do \
+ { \
+ (dst) = (src); \
+ switch ((dst).type) \
+ { \
+ case GVT_ARRAY: \
+ g_object_ref(G_OBJECT((dst).array)); \
+ break; \
+ case GVT_RECORD: \
+ g_object_ref(G_OBJECT((dst).record)); \
+ break; \
+ case GVT_STREAM: \
+ g_object_ref(G_OBJECT((dst).stream)); \
+ break; \
+ default: \
+ break; \
+ } \
+ } \
+ while (0)
+
+
+#define EXIT_RESOLVED_VALUE(v) \
+ switch ((v).type) \
+ { \
+ case GVT_ARRAY: \
+ g_clear_object(&(v).array); \
+ break; \
+ case GVT_RECORD: \
+ g_clear_object(&(v).record); \
+ break; \
+ case GVT_STREAM: \
+ g_clear_object(&(v).stream); \
+ break; \
+ default: \
+ break; \
+ }
+
+
+/* Interprète une expression en une valeur quelconque. */
+bool resolve_kaitai_expression_as_any(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en valeur ciblée entière. */
+bool resolve_kaitai_expression_as_integer(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en valeur ciblée booléenne. */
+bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en série d'octets. */
+bool resolve_kaitai_expression_as_bytes(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en flux de données pour Kaitai. */
+bool resolve_kaitai_expression_as_stream(const kaitai_scope_t *, const char *, size_t, GKaitaiStream **);
+
+
+
+#endif /* _PLUGINS_KAITAI_EXPRESSION_H */
diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y
new file mode 100644
index 0000000..9745dc8
--- /dev/null
+++ b/plugins/kaitai/grammar.y
@@ -0,0 +1,1919 @@
+
+%{
+
+#include "expression.h"
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(yyscan_t, const kaitai_scope_t *, resolved_value_t *, const char *);
+
+/* Interprète une expression en une valeur quelconque. */
+static bool _resolve_kaitai_expression_as_any(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Traduit les éventuels champs impliqués dans une expression. */
+static bool reduce_resolved_kaitai_expression(resolved_value_t *);
+
+
+%}
+
+
+%code requires {
+
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include "expression.h"
+#include "record.h"
+#include "records/bits.h"
+#include "records/delayed.h"
+#include "records/item.h"
+#include "records/list.h"
+
+}
+
+%union {
+
+ resolved_value_t value; /* Valeur portée */
+
+ unsigned long long unsigned_integer; /* Valeur entière #1 */
+ signed long long signed_integer; /* Valeur entière #2 */
+ double floating_number; /* Valeur à virgule flottante */
+ sized_string_t sized_cstring; /* Chaîne de caractères */
+ char byte; /* Octet unique */
+
+}
+
+
+/**
+ * Cf.
+ * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950
+ */
+
+%define api.pure full
+
+%parse-param { yyscan_t yyscanner } { const kaitai_scope_t *locals } { resolved_value_t *resolved }
+%lex-param { yyscan_t yyscanner }
+
+%code provides {
+
+#define YY_DECL \
+ int kaitai_lex(YYSTYPE *yylval_param, yyscan_t yyscanner)
+
+YY_DECL;
+
+
+
+#define SET_ERR(out) \
+ out.type = GVT_ERROR
+
+#define EXIT_WITH_ERR(out, lbl) \
+ do \
+ { \
+ SET_ERR(out); \
+ goto exit_ ## lbl; \
+ } \
+ while (0)
+
+#define CHECK_TYPE(arg, tp, out, lbl) \
+ if (arg.type != tp) EXIT_WITH_ERR(out, lbl)
+
+#define CHECK_TYPES(arg, tp1, tp2, out, lbl) \
+ if (arg.type != tp1 && arg.type != tp2) EXIT_WITH_ERR(out, lbl)
+
+#define REDUCE_EXPR(arg, out, lbl) \
+ if (!reduce_resolved_kaitai_expression(&arg)) \
+ EXIT_WITH_ERR(out, lbl)
+
+#define REDUCE_NUMERIC_EXPR(arg, out, lbl) \
+ if (!reduce_resolved_kaitai_expression(&arg)) \
+ EXIT_WITH_ERR(out, lbl); \
+ if (arg.type == GVT_SIGNED_INTEGER && arg.signed_integer >= 0) \
+ { \
+ arg.unsigned_integer = arg.signed_integer; \
+ arg.type = GVT_UNSIGNED_INTEGER; \
+ }
+
+
+#define ARITHMETIC_ADD_CODE(op1, op2, out, lbl) \
+ switch (op1.type) \
+ { \
+ case GVT_UNSIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = op1.unsigned_integer + op2.unsigned_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ if (op1.unsigned_integer < -op2.signed_integer) \
+ { \
+ out.signed_integer = op1.unsigned_integer + op2.signed_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else \
+ { \
+ out.unsigned_integer = op1.unsigned_integer + op2.signed_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.unsigned_integer + op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_SIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ if (-op1.signed_integer > op2.unsigned_integer) \
+ { \
+ out.signed_integer = op1.signed_integer + op2.unsigned_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else \
+ { \
+ out.unsigned_integer = op1.signed_integer + op2.unsigned_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.signed_integer = op1.signed_integer + op2.signed_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.signed_integer + op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_FLOAT: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.floating_number = op1.floating_number + op2.unsigned_integer; \
+ out.type = GVT_FLOAT; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.floating_number = op1.floating_number + op2.signed_integer; \
+ out.type = GVT_FLOAT; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.floating_number + op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ default: \
+ EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ }
+
+
+#define ARITHMETIC_SUB_CODE(op1, op2, out, lbl) \
+ switch (op1.type) \
+ { \
+ case GVT_UNSIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ if (op1.unsigned_integer < op2.unsigned_integer) \
+ { \
+ out.signed_integer = op1.unsigned_integer - op2.unsigned_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else \
+ { \
+ out.unsigned_integer = op1.unsigned_integer - op2.unsigned_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = op1.unsigned_integer - op2.signed_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.unsigned_integer - op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_SIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.signed_integer = op1.signed_integer - op2.unsigned_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ if (op1.signed_integer < op2.signed_integer) \
+ { \
+ out.signed_integer = op1.signed_integer - op2.signed_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else \
+ { \
+ out.unsigned_integer = op1.signed_integer - op2.signed_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.signed_integer - op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_FLOAT: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.floating_number = op1.floating_number - op2.unsigned_integer; \
+ out.type = GVT_FLOAT; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.floating_number = op1.floating_number - op2.signed_integer; \
+ out.type = GVT_FLOAT; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.floating_number - op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ default: \
+ EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ }
+
+
+#define ARITHMETIC_GENOP_CODE(op1, op2, _meth_, out, lbl) \
+ switch (op1.type) \
+ { \
+ case GVT_UNSIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = op1.unsigned_integer _meth_ op2.unsigned_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.signed_integer = op1.unsigned_integer _meth_ op2.signed_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.unsigned_integer _meth_ op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_SIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = op1.signed_integer _meth_ op2.unsigned_integer; \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = op1.signed_integer _meth_ op2.signed_integer; \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.signed_integer _meth_ op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_FLOAT: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = op1.floating_number _meth_ op2.unsigned_integer; \
+ out.type = GVT_FLOAT; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.signed_integer = op1.floating_number _meth_ op2.signed_integer; \
+ out.type = GVT_FLOAT; \
+ } \
+ else if (op2.type == GVT_FLOAT) \
+ { \
+ out.floating_number = op1.floating_number _meth_ op2.floating_number; \
+ out.type = GVT_FLOAT; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ default: \
+ EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ }
+
+
+/**
+ * Cf. https://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers/52529440#52529440
+ */
+#define EUCLIDEAN_MODULO(a, b, r) \
+ r = a % (signed long long)b; \
+ if (r < 0) \
+ r = (b < 0) ? r - b : r + b; \
+
+
+#define ARITHMETIC_MOD_CODE(op1, op2, out, lbl) \
+ switch (op1.type) \
+ { \
+ case GVT_UNSIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ EUCLIDEAN_MODULO(op1.unsigned_integer, op2.unsigned_integer, out.unsigned_integer); \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ EUCLIDEAN_MODULO(op1.unsigned_integer, op2.signed_integer, out.signed_integer); \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_SIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ EUCLIDEAN_MODULO(op1.signed_integer, op2.unsigned_integer, out.signed_integer); \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ EUCLIDEAN_MODULO(op1.signed_integer, op2.signed_integer, out.signed_integer); \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ default: \
+ EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ }
+
+
+#define RELATIONAL_CODE(op1, op2, _meth_, out, lbl) \
+ switch (op1.type) \
+ { \
+ case GVT_UNSIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.status = (op1.unsigned_integer _meth_ op2.unsigned_integer); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.status = (op1.unsigned_integer _meth_ op2.signed_integer); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_SIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.status = (op1.signed_integer _meth_ op2.unsigned_integer); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else if (op2.type == GVT_SIGNED_INTEGER) \
+ { \
+ out.status = (op1.signed_integer _meth_ op2.signed_integer); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_BYTES: \
+ if (op2.type == GVT_BYTES) \
+ { \
+ int __ret; \
+ __ret = szmemcmp(&op1.bytes, &op2.bytes); \
+ out.status = (__ret _meth_ 0); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else if (op2.type == GVT_ARRAY) \
+ { \
+ sized_string_t __abytes_2; \
+ int __ret; \
+ if (!g_kaitai_array_convert_to_bytes(op2.array, &__abytes_2)) \
+ EXIT_WITH_ERR(out, lbl); \
+ __ret = szmemcmp(&op1.bytes, &__abytes_2); \
+ exit_szstr(&__abytes_2); \
+ out.status = (__ret _meth_ 0); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_ARRAY: \
+ if (op2.type == GVT_BYTES) \
+ { \
+ sized_string_t __abytes_1; \
+ int __ret; \
+ if (!g_kaitai_array_convert_to_bytes(op1.array, &__abytes_1)) \
+ EXIT_WITH_ERR(out, lbl); \
+ __ret = szmemcmp(&__abytes_1, &op2.bytes); \
+ exit_szstr(&__abytes_1); \
+ out.status = (__ret _meth_ 0); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else if (op2.type == GVT_ARRAY) \
+ { \
+ sized_string_t __abytes_1; \
+ sized_string_t __abytes_2; \
+ int __ret; \
+ if (!g_kaitai_array_convert_to_bytes(op1.array, &__abytes_1)) \
+ EXIT_WITH_ERR(out, lbl); \
+ if (!g_kaitai_array_convert_to_bytes(op2.array, &__abytes_2)) \
+ { \
+ exit_szstr(&__abytes_1); \
+ EXIT_WITH_ERR(out, lbl); \
+ } \
+ __ret = szmemcmp(&__abytes_1, &__abytes_2); \
+ exit_szstr(&__abytes_1); \
+ exit_szstr(&__abytes_2); \
+ out.status = (__ret _meth_ 0); \
+ out.type = GVT_BOOLEAN; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_STREAM: \
+ if (op2.type == GVT_STREAM) \
+ { \
+ GBinContent *__cnt_1; \
+ GBinContent *__cnt_2; \
+ __cnt_1 = g_kaitai_stream_get_content(op1.stream); \
+ __cnt_2 = g_kaitai_stream_get_content(op2.stream); \
+ out.status = (__cnt_1 _meth_ __cnt_2); \
+ out.type = GVT_BOOLEAN; \
+ g_object_unref(G_OBJECT(__cnt_1)); \
+ g_object_unref(G_OBJECT(__cnt_2)); \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ default: \
+ EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ }
+
+
+#define BITWISE_CODE(op1, op2, _meth_, out, lbl) \
+ switch (op1.type) \
+ { \
+ case GVT_UNSIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.unsigned_integer = (op1.unsigned_integer _meth_ op2.unsigned_integer); \
+ out.type = GVT_UNSIGNED_INTEGER; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ case GVT_SIGNED_INTEGER: \
+ if (op2.type == GVT_UNSIGNED_INTEGER) \
+ { \
+ out.signed_integer = (op1.signed_integer _meth_ op2.unsigned_integer); \
+ out.type = GVT_SIGNED_INTEGER; \
+ } \
+ else EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ default: \
+ EXIT_WITH_ERR(out, lbl); \
+ break; \
+ \
+ }
+
+
+
+
+}
+
+
+%token <unsigned_integer> UNSIGNED_INTEGER
+%token <signed_integer> SIGNED_INTEGER
+%token <floating_number> FLOAT
+
+%token <sized_cstring> IDENTIFIER
+%token <sized_cstring> RAW_BYTES
+%token <byte> RAW_BYTE
+%token <sized_cstring> RAW_BYTES_WITH_ENDING_DOT
+%token <sized_cstring> PLAIN_BYTES
+
+%token <sized_cstring> ENCODING_NAME
+
+
+%token PLUS "+"
+%token MINUS "-"
+%token MUL "*"
+%token DIV "/"
+%token MOD "%"
+
+%token LT "<"
+%token LE "<="
+%token EQ "=="
+%token NE "!="
+%token GT ">"
+%token GE ">="
+
+%token SHIFT_LEFT "<<"
+%token SHIFT_RIGHT ">>"
+%token BIT_AND "&"
+%token BIT_OR "|"
+%token BIT_XOR "^"
+
+%token NOT "not"
+%token AND "and"
+%token OR "or"
+
+%token PAREN_O "("
+%token PAREN_C ")"
+%token HOOK_O "["
+%token HOOK_C "]"
+%token COMMA ","
+%token DOT "."
+
+%token QMARK "?"
+%token COLON ":"
+%token DOUBLE_COLON "::"
+
+%token METH_SIZE ".size"
+%token METH_LENGTH ".length"
+%token METH_REVERSE ".reverse"
+%token METH_SUBSTRING ".substring"
+%token METH_TO_I ".to_i"
+%token METH_TO_I_RAD ".to_i("
+%token METH_TO_S ".to_s"
+%token METH_TO_S_ENC ".to_s("
+
+%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"
+
+
+ //%type <value> operand
+%type <value> any_expr
+ //%type <value> arithm_expr
+ //%type <value> arithm_op
+
+%type <value> boolean
+
+
+
+%type <value> arithmetic_expr
+%type <value> relational_expr
+%type <value> logical_expr
+%type <value> bitwise_expr
+%type <value> ternary_expr
+
+%type <value> convert_2_bytes
+%type <value> convert_2_integer
+
+
+%type <value> integer
+
+%type <value> float
+
+%type <value> bytes
+
+%type <value> bytes_concat
+%type <value> raw_bytes
+
+
+%type <value> array
+%type <value> array_items
+
+
+%type <value> field
+%type <value> enumeration
+%type <value> stream
+%type <value> stream_meths
+
+
+
+%destructor { printf("----------------------freeing %p...\n", &$$), fflush(NULL); } <*>
+
+
+ //%type <integer> INTEGER
+ //
+
+ //%type <integer> arithm_expr
+ //%type <integer> arithm_op
+
+ //%type <boolean> bool_expr
+ //%type <boolean> relational_op logical_op ternary_op
+
+
+ //%type <integer> constant
+
+
+
+
+
+/**
+ * Cf. https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
+ */
+
+
+
+
+
+%left "?" ":"
+
+%left OR
+%left "and"
+
+/* 13 */
+%left "|"
+
+/* 12 */
+%left "^"
+
+/* 11 */
+%left "&"
+
+%left LT LE EQ NE GT GE
+
+/* 7 */
+%left "<<" ">>"
+
+
+%right NOT
+
+%left PLUS MINUS
+%left "*"
+%left DIV MOD
+
+
+%left "["
+
+
+
+
+%left ".size"
+%left ".length"
+%left ".reverse"
+%left ".substring"
+%left ".to_i"
+%left ".to_i("
+%left ".to_s"
+%left ".to_s("
+
+%left "._io"
+
+%left "."
+
+/* 1 */
+%right "::"
+
+
+%%
+
+ expressions : any_expr { *resolved = $1; }
+ ;
+
+ any_expr : boolean { $$ = $1; }
+ | bytes { $$ = $1; }
+ | integer { $$ = $1; }
+ | float { $$ = $1; }
+ | array { $$ = $1; }
+ | field { $$ = $1; }
+ | enumeration { $$ = $1; }
+ | stream { $$ = $1; }
+ | stream_meths { $$ = $1; }
+ | arithmetic_expr { $$ = $1; }
+ | relational_expr { $$ = $1; }
+ | logical_expr { $$ = $1; }
+ | bitwise_expr { $$ = $1; }
+ | ternary_expr { $$ = $1; }
+ | convert_2_bytes { $$ = $1; }
+ | convert_2_integer { $$ = $1; }
+ | "(" any_expr ")" { $$ = $2; }
+ ;
+
+
+/* Expressions impliquants formules et opérandes */
+
+ arithmetic_expr : any_expr "+" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_plus);
+ REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_plus);
+
+ if ($1.type == GVT_BYTES && $3.type == GVT_BYTES)
+ {
+ $$.bytes.len = $1.bytes.len + $3.bytes.len;
+ $$.bytes.data = malloc($$.bytes.len);
+
+ memcpy($$.bytes.data, $1.bytes.data, $1.bytes.len);
+ memcpy($$.bytes.data + $1.bytes.len, $3.bytes.data, $3.bytes.len);
+
+ $$.type = GVT_BYTES;
+
+ }
+
+ else if ($1.type == GVT_BYTES && $3.type == GVT_ARRAY)
+ {
+ sized_string_t __abytes_2;
+
+ if (!g_kaitai_array_convert_to_bytes($3.array, &__abytes_2))
+ EXIT_WITH_ERR($$, arithmetic_expr_plus);
+
+ $$.bytes.len = $1.bytes.len + __abytes_2.len;
+ $$.bytes.data = malloc($$.bytes.len);
+
+ memcpy($$.bytes.data, $1.bytes.data, $1.bytes.len);
+ memcpy($$.bytes.data + $1.bytes.len, __abytes_2.data, __abytes_2.len);
+
+ $$.type = GVT_BYTES;
+
+ exit_szstr(&__abytes_2);
+
+ }
+
+ else
+ {
+ ARITHMETIC_ADD_CODE($1, $3, $$, arithmetic_expr_plus);
+ }
+
+ exit_arithmetic_expr_plus:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "-" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_minus);
+ REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_minus);
+ ARITHMETIC_SUB_CODE($1, $3, $$, arithmetic_expr_minus);
+ exit_arithmetic_expr_minus:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "*" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_mul);
+ REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_mul);
+ ARITHMETIC_GENOP_CODE($1, $3, *, $$, arithmetic_expr_mul);
+ exit_arithmetic_expr_mul:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "/" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_div);
+ REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_div);
+ ARITHMETIC_GENOP_CODE($1, $3, /, $$, arithmetic_expr_div);
+ exit_arithmetic_expr_div:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "%" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_mod);
+ REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_mod);
+ ARITHMETIC_MOD_CODE($1, $3, $$, arithmetic_expr_mod);
+ exit_arithmetic_expr_mod:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ ;
+
+
+ relational_expr : any_expr "<" any_expr
+ {
+ REDUCE_EXPR($1, $$, relational_expr_lt);
+ REDUCE_EXPR($3, $$, relational_expr_lt);
+ RELATIONAL_CODE($1, $3, <, $$, relational_expr_lt);
+ exit_relational_expr_lt:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "<=" any_expr
+ {
+ REDUCE_EXPR($1, $$, relational_expr_le);
+ REDUCE_EXPR($3, $$, relational_expr_le);
+ RELATIONAL_CODE($1, $3, <=, $$, relational_expr_le);
+ exit_relational_expr_le:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "==" any_expr
+ {
+ REDUCE_EXPR($1, $$, relational_expr_eq);
+ REDUCE_EXPR($3, $$, relational_expr_eq);
+ RELATIONAL_CODE($1, $3, ==, $$, relational_expr_eq);
+ exit_relational_expr_eq:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "!=" any_expr
+ {
+ REDUCE_EXPR($1, $$, relational_expr_ne);
+ REDUCE_EXPR($3, $$, relational_expr_ne);
+ RELATIONAL_CODE($1, $3, !=, $$, relational_expr_ne);
+ exit_relational_expr_ne:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr ">" any_expr
+ {
+ REDUCE_EXPR($1, $$, relational_expr_gt);
+ REDUCE_EXPR($3, $$, relational_expr_gt);
+ RELATIONAL_CODE($1, $3, >, $$, relational_expr_gt);
+ exit_relational_expr_gt:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr ">=" any_expr
+ {
+ REDUCE_EXPR($1, $$, relational_expr_ge);
+ REDUCE_EXPR($3, $$, relational_expr_ge);
+ RELATIONAL_CODE($1, $3, >=, $$, relational_expr_ge);
+ exit_relational_expr_ge:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ ;
+
+
+ bitwise_expr : any_expr "<<" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_shift_left);
+ REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_shift_left);
+ BITWISE_CODE($1, $3, <<, $$, bitwise_expr_shift_left);
+ exit_bitwise_expr_shift_left:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr ">>" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_shift_right);
+ REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_shift_right);
+ BITWISE_CODE($1, $3, >>, $$, bitwise_expr_shift_right);
+ exit_bitwise_expr_shift_right:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "&" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_and);
+ REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_and);
+ BITWISE_CODE($1, $3, &, $$, bitwise_expr_and);
+ exit_bitwise_expr_and:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "|" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_or);
+ REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_or);
+ BITWISE_CODE($1, $3, |, $$, bitwise_expr_or);
+ exit_bitwise_expr_or:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "^" any_expr
+ {
+ REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_xor);
+ REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_xor);
+ BITWISE_CODE($1, $3, ^, $$, bitwise_expr_xor);
+ exit_bitwise_expr_xor:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ ;
+
+
+ logical_expr : "not" any_expr
+ {
+ REDUCE_EXPR($2, $$, logical_expr_not);
+ CHECK_TYPE($2, GVT_BOOLEAN, $$, logical_expr_not);
+ $$.status = !$2.status;
+ $$.type = GVT_BOOLEAN;
+ exit_logical_expr_not:
+ EXIT_RESOLVED_VALUE($2);
+ }
+ | any_expr "and" any_expr
+ {
+ REDUCE_EXPR($1, $$, logical_expr_and);
+ CHECK_TYPE($1, GVT_BOOLEAN, $$, logical_expr_and);
+ REDUCE_EXPR($3, $$, logical_expr_and);
+ CHECK_TYPE($3, GVT_BOOLEAN, $$, logical_expr_and);
+ $$.status = $1.status && $3.status;
+ $$.type = GVT_BOOLEAN;
+ exit_logical_expr_and:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ | any_expr "or" any_expr
+ {
+ REDUCE_EXPR($1, $$, logical_expr_or);
+ CHECK_TYPE($1, GVT_BOOLEAN, $$, logical_expr_or);
+ REDUCE_EXPR($3, $$, logical_expr_or);
+ CHECK_TYPE($3, GVT_BOOLEAN, $$, logical_expr_or);
+ $$.status = $1.status || $3.status;
+ $$.type = GVT_BOOLEAN;
+ exit_logical_expr_or:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ ;
+
+
+ ternary_expr : any_expr "?" any_expr ":" any_expr
+ {
+ REDUCE_EXPR($1, $$, ternary_expr);
+ CHECK_TYPE($1, GVT_BOOLEAN, $$, ternary_expr);
+ if ($1.status)
+ COPY_RESOLVED_VALUE($$, $3);
+ else
+ COPY_RESOLVED_VALUE($$, $5);
+ exit_ternary_expr:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ EXIT_RESOLVED_VALUE($5);
+ }
+ ;
+
+
+/* Conversions et méthodes particulières de types */
+
+ convert_2_bytes : any_expr ".to_s"
+ {
+ int __ret;
+
+ if ($1.type == GVT_UNSIGNED_INTEGER)
+ {
+ __ret = asprintf(&$$.bytes.data, "%llu", $1.unsigned_integer);
+ if (__ret == -1) EXIT_WITH_ERR($$, convert_2_bytes_to_s);
+
+ $$.bytes.len = __ret;
+ $$.type = GVT_BYTES;
+
+ }
+ else if ($1.type == GVT_SIGNED_INTEGER)
+ {
+ __ret = asprintf(&$$.bytes.data, "%lld", $1.signed_integer);
+ if (__ret == -1) EXIT_WITH_ERR($$, convert_2_bytes_to_s);
+
+ $$.bytes.len = __ret;
+ $$.type = GVT_BYTES;
+
+ }
+ else
+ EXIT_WITH_ERR($$, convert_2_bytes_to_s);
+
+ exit_convert_2_bytes_to_s:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ | any_expr ".to_s(" ENCODING_NAME ")"
+ {
+ /**
+ * Cf. https://fossies.org/linux/libiconv/man/iconv_open.3.html
+ */
+
+ char *__fromcode;
+ gsize __bytes_read;
+ gsize __bytes_written;
+
+ if ($1.type != GVT_BYTES)
+ EXIT_WITH_ERR($$, convert_2_bytes_to_s_encoding);
+
+ __fromcode = strndup($3.data, $3.len);
+
+ $$.bytes.data = g_convert($1.bytes.data, $1.bytes.len,
+ __fromcode, "", &__bytes_read, &__bytes_written, NULL);
+
+ free(__fromcode);
+
+ if (__bytes_read != $1.bytes.len)
+ EXIT_WITH_ERR($$, convert_2_bytes_to_s_encoding);
+
+ $$.bytes.len = __bytes_written;
+ $$.type = GVT_BYTES;
+
+ exit_convert_2_bytes_to_s_encoding:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ ;
+
+
+ convert_2_integer : any_expr ".length"
+ {
+ if ($1.type != GVT_BYTES)
+ EXIT_WITH_ERR($$, convert_2_integer_to_s);
+
+ $$.unsigned_integer = $1.bytes.len;
+ $$.type = GVT_UNSIGNED_INTEGER;
+
+ exit_convert_2_integer_to_s:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ | any_expr ".to_i"
+ {
+ char *__n;
+ char *__end;
+
+ if ($1.type == GVT_FLOAT)
+ {
+ if ($1.floating_number < 0)
+ {
+ $$.signed_integer = $1.floating_number;
+ $$.type = GVT_SIGNED_INTEGER;
+ }
+ else
+ {
+ $$.unsigned_integer = $1.floating_number;
+ $$.type = GVT_UNSIGNED_INTEGER;
+ }
+
+ }
+
+ else if ($1.type == GVT_BOOLEAN)
+ {
+ $$.unsigned_integer = $1.status ? 1 : 0;
+ $$.type = GVT_UNSIGNED_INTEGER;
+ }
+
+ else if ($1.type == GVT_BYTES)
+ {
+ if ($1.bytes.len == 0)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ __n = malloc($1.bytes.len + 1);
+ memcpy(__n, $1.bytes.data, $1.bytes.len);
+ __n[$1.bytes.len] = '\0';
+
+ if ($1.bytes.data[0] == '-')
+ {
+ if ($1.bytes.len == 1)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ $$.signed_integer = strtoll(__n, &__end, 10);
+ $$.type = GVT_SIGNED_INTEGER;
+
+ if (errno == EINVAL || errno == ERANGE)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ if (__end != &__n[$1.bytes.len])
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ }
+ else
+ {
+ if ($1.bytes.len == 1)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ $$.unsigned_integer = strtoull(__n, &__end, 10);
+ $$.type = GVT_UNSIGNED_INTEGER;
+
+ if (errno == EINVAL || errno == ERANGE)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ if (__end != &__n[$1.bytes.len])
+ EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ }
+
+ free(__n);
+
+ }
+
+ else EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+ exit_convert_2_integer_to_i:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ | any_expr ".to_i(" any_expr ")"
+ {
+ int __base;
+ char *__n;
+ char *__end;
+
+ if ($1.type == GVT_BYTES)
+ {
+ if ($1.bytes.len == 0)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ if ($3.type == GVT_UNSIGNED_INTEGER)
+ {
+ __base = $3.unsigned_integer;
+ if (__base < 2)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+ }
+ else if ($3.type == GVT_SIGNED_INTEGER)
+ {
+ __base = $3.signed_integer;
+ if (__base < 2)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+ }
+ else EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ __n = malloc($1.bytes.len + 1);
+ memcpy(__n, $1.bytes.data, $1.bytes.len);
+ __n[$1.bytes.len] = '\0';
+
+ if ($1.bytes.data[0] == '-')
+ {
+ if ($1.bytes.len == 1)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ $$.signed_integer = strtoll(__n, &__end, __base);
+ $$.type = GVT_SIGNED_INTEGER;
+
+ if (errno == EINVAL || errno == ERANGE)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ if (__end != &__n[$1.bytes.len])
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ }
+ else
+ {
+ if ($1.bytes.len == 1)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ $$.unsigned_integer = strtoull(__n, &__end, __base);
+ $$.type = GVT_UNSIGNED_INTEGER;
+
+ if (errno == EINVAL || errno == ERANGE)
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ if (__end != &__n[$1.bytes.len])
+ EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ }
+
+ free(__n);
+
+ }
+
+ else EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+ exit_convert_2_integer_to_i_base:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ | any_expr ".size"
+ {
+ GRecordList *__list;
+
+ if ($1.type != GVT_RECORD) EXIT_WITH_ERR($$, convert_2_integer_size);
+ if (!G_IS_RECORD_LIST($1.record)) EXIT_WITH_ERR($$, convert_2_integer_size);
+
+ __list = G_RECORD_LIST($1.record);
+
+ $$.unsigned_integer = g_record_list_count_records(__list);
+ $$.type = GVT_UNSIGNED_INTEGER;
+
+ exit_convert_2_integer_size:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ ;
+
+
+/* Types de base */
+
+ boolean : "true"
+ {
+ $$.status = true;
+ $$.type = GVT_BOOLEAN;
+ }
+ | "false"
+ {
+ $$.status = false;
+ $$.type = GVT_BOOLEAN;
+ }
+ ;
+
+
+ integer : UNSIGNED_INTEGER
+ {
+ $$.unsigned_integer = $1;
+ $$.type = GVT_UNSIGNED_INTEGER;
+ }
+ | SIGNED_INTEGER
+ {
+ $$.signed_integer = $1;
+ $$.type = GVT_SIGNED_INTEGER;
+ }
+ ;
+
+
+ float : FLOAT
+ {
+ $$.floating_number = $1;
+ $$.type = GVT_FLOAT;
+ }
+ ;
+
+
+ bytes : bytes_concat { $$ = $1; }
+ | PLAIN_BYTES
+ {
+ $$.bytes.len = $1.len;
+ $$.bytes.data = malloc($1.len);
+ memcpy($$.bytes.data, $1.data, $1.len);
+ $$.type = GVT_BYTES;
+ }
+ | any_expr ".reverse"
+ {
+ size_t __i;
+
+ CHECK_TYPE($1, GVT_BYTES, $$, bytes_reverse);
+
+ $$.bytes.data = malloc($1.bytes.len);
+ $$.bytes.len = $1.bytes.len;
+
+ for (__i = 0; __i < $1.bytes.len; __i++)
+ $$.bytes.data[__i] = $1.bytes.data[$1.bytes.len - __i - 1];
+
+ $$.type = GVT_BYTES;
+
+ exit_bytes_reverse:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ | any_expr ".substring" "(" any_expr "," any_expr ")"
+ {
+ unsigned long long __from;
+ unsigned long long __to;
+
+ REDUCE_NUMERIC_EXPR($4, $$, bytes_reverse);
+ CHECK_TYPES($4, GVT_UNSIGNED_INTEGER, GVT_SIGNED_INTEGER, $$, bytes_substring);
+ REDUCE_NUMERIC_EXPR($6, $$, bytes_reverse);
+ CHECK_TYPES($6, GVT_UNSIGNED_INTEGER, GVT_SIGNED_INTEGER, $$, bytes_substring);
+
+ __from = ($4.type == GVT_UNSIGNED_INTEGER ? $4.unsigned_integer : $4.signed_integer);
+ __to = ($6.type == GVT_UNSIGNED_INTEGER ? $6.unsigned_integer : $6.signed_integer);
+
+ if (__from > __to) EXIT_WITH_ERR($$, bytes_substring);
+ if (__to >= $1.bytes.len) EXIT_WITH_ERR($$, bytes_substring);
+
+ $$.bytes.len = __to - __from + 1;
+ $$.bytes.data = malloc($$.bytes.len);
+
+ memcpy($$.bytes.data, &$1.bytes.data[__from], $$.bytes.len);
+
+ $$.type = GVT_BYTES;
+
+ exit_bytes_substring:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($4);
+ EXIT_RESOLVED_VALUE($6);
+ }
+ ;
+
+ bytes_concat : raw_bytes { $$ = $1; };
+ | bytes_concat raw_bytes
+ {
+ $$.bytes.len = $1.bytes.len + $2.bytes.len;
+ $$.bytes.data = malloc($$.bytes.len);
+ memcpy($$.bytes.data, $1.bytes.data, $1.bytes.len);
+ memcpy($$.bytes.data + $1.bytes.len, $2.bytes.data, $2.bytes.len);
+ $$.type = GVT_BYTES;
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($2);
+ }
+ ;
+
+ raw_bytes : RAW_BYTES
+ {
+ $$.bytes.len = $1.len;
+ $$.bytes.data = malloc($1.len);
+ memcpy($$.bytes.data, $1.data, $1.len);
+ $$.type = GVT_BYTES;
+ }
+ | RAW_BYTE
+ {
+ $$.bytes.len = 1;
+ $$.bytes.data = malloc(1);
+ $$.bytes.data[0] = $1;
+ $$.type = GVT_BYTES;
+ }
+ | RAW_BYTES_WITH_ENDING_DOT
+ {
+ $$.bytes.len = $1.len;
+ $$.bytes.data = malloc($1.len);
+ memcpy($$.bytes.data, $1.data, $1.len);
+ $$.type = GVT_BYTES;
+ }
+ ;
+
+
+/* Tableau d'éléments variés */
+
+ array : "[" "]"
+ {
+ $$.array = g_kaitai_array_new();
+ $$.type = GVT_ARRAY;
+ }
+ | "[" array_items "]"
+ {
+ $$ = $2;
+ }
+ ;
+
+
+ array_items : any_expr
+ {
+ $$.array = g_kaitai_array_new();
+ $$.type = GVT_ARRAY;
+
+ g_kaitai_array_append_item($$.array, &$1);
+
+ EXIT_RESOLVED_VALUE($1);
+
+ }
+ | array_items "," any_expr
+ {
+ $$ = $1;
+ g_kaitai_array_append_item($$.array, &$3);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ ;
+
+
+/* Accès aux objets Kaitai manipulés */
+
+ field : IDENTIFIER
+ {
+ $$.record = g_match_record_find_by_name(locals->parent,
+ $1.data, $1.len,
+ DIRECT_SEARCH_DEEP_LEVEL);
+
+ if ($$.record != NULL)
+ $$.type = GVT_RECORD;
+
+ /* Si aucune correspondance, le contenu brut est utilisé */
+ else
+ {
+ $$.bytes.len = $1.len;
+ $$.bytes.data = malloc($1.len);
+ memcpy($$.bytes.data, $1.data, $1.len);
+ $$.type = GVT_BYTES;
+ }
+
+ }
+ | "_root"
+ {
+ $$.record = get_root_record(locals);
+ if ($$.record == NULL) SET_ERR($$);
+ else $$.type = GVT_RECORD;
+ }
+ | "_parent"
+ {
+ $$.record = get_parent_record(locals);
+ if ($$.record == NULL) SET_ERR($$);
+ else $$.type = GVT_RECORD;
+ }
+ | "_"
+ {
+ $$.record = get_last_record(locals);
+ if ($$.record == NULL) SET_ERR($$);
+ else $$.type = GVT_RECORD;
+ }
+ | any_expr "." IDENTIFIER
+ {
+ if ($1.type != GVT_RECORD)
+ EXIT_WITH_ERR($$, field_dot);
+
+ $$.record = g_match_record_find_by_name($1.record,
+ $3.data, $3.len,
+ DIRECT_SEARCH_DEEP_LEVEL);
+
+ if ($$.record == NULL)
+ EXIT_WITH_ERR($$, field_dot);
+
+ $$.type = GVT_RECORD;
+
+ exit_field_dot:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ | any_expr "[" any_expr "]"
+ {
+ size_t __index;
+ GRecordList *__list;
+ size_t __count;
+ GKaitaiArray *__array;
+
+ /* Indice de l'élément auquel accéder */
+
+ REDUCE_NUMERIC_EXPR($3, $$, field_indexed);
+
+ if ($3.type == GVT_UNSIGNED_INTEGER)
+ __index = $3.unsigned_integer;
+ else
+ EXIT_WITH_ERR($$, field_indexed);
+
+ /* Série à consulter */
+
+ REDUCE_EXPR($1, $$, field_indexed);
+
+ if ($1.type == GVT_RECORD && G_IS_RECORD_LIST($1.record))
+ {
+ __list = G_RECORD_LIST($1.record);
+ __count = g_record_list_count_records(__list);
+
+ if (__index >= __count)
+ EXIT_WITH_ERR($$, field_indexed);
+
+ $$.record = g_record_list_get_record(__list, __index);
+
+ if ($$.record == NULL)
+ EXIT_WITH_ERR($$, field_indexed);
+
+ $$.type = GVT_RECORD;
+
+ }
+
+ else if ($1.type == GVT_ARRAY)
+ {
+ __array = G_KAITAI_ARRAY($1.array);
+ __count = g_kaitai_array_count_items(__array);
+
+ if (__index >= __count)
+ EXIT_WITH_ERR($$, field_indexed);
+
+ if (!g_kaitai_array_get_item(__array, __index, &$$))
+ EXIT_WITH_ERR($$, field_indexed);
+
+ }
+
+ else
+ EXIT_WITH_ERR($$, field_indexed);
+
+ exit_field_indexed:
+ EXIT_RESOLVED_VALUE($1);
+ EXIT_RESOLVED_VALUE($3);
+ }
+ ;
+
+
+ enumeration : IDENTIFIER "::" IDENTIFIER
+ {
+ if (!g_match_record_resolve_enum(locals->parent, &$1, &$3, &$$))
+ SET_ERR($$);
+ }
+
+
+ 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;
+
+ if ($1.type != GVT_RECORD)
+ EXIT_WITH_ERR($$, stream_io);
+
+ __content = g_match_record_get_content($1.record);
+ g_match_record_get_range($1.record, &__range);
+
+ $$.stream = g_kaitai_stream_new(__content, get_mrange_addr(&__range));
+ $$.type = GVT_STREAM;
+
+ g_object_unref(G_OBJECT(__content));
+
+ exit_stream_io:
+ EXIT_RESOLVED_VALUE($1);
+ }
+ ;
+
+ stream_meths : stream ".eof"
+ {
+ $$.status = g_kaitai_stream_has_reached_eof($1.stream);;
+ $$.type = GVT_BOOLEAN;
+
+ EXIT_RESOLVED_VALUE($1);
+
+ }
+ ;
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : yyscanner = décodeur impliqué dans le processus. *
+* locals = variables locales pour les résolutions de types. *
+* out = valeur entière résultante. [OUT] *
+* msg = message d'erreur. *
+* *
+* Description : Affiche un message d'erreur suite à l'analyse en échec. *
+* *
+* Retour : 0 *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int yyerror(yyscan_t yyscanner, const kaitai_scope_t *locals, resolved_value_t *resolved, const char *msg)
+{
+ printf("YYERROR line %d: %s\n", yyget_lineno(yyscanner), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* out = valeur générique résultante. [OUT] *
+* *
+* Description : Interprète une expression en une valeur quelconque. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool _resolve_kaitai_expression_as_any(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+ bool result; /* Bilan à renvoyer */
+ yyscan_t lexstate; /* Gestion d'analyse lexicale */
+ char *real_text; /* Zone de travail effective */
+ size_t real_length; /* Taille associée */
+ YY_BUFFER_STATE state; /* Contexte d'analyse */
+ int status; /* Bilan d'une analyse */
+
+ result = false;
+
+ kaitai_lex_init(&lexstate);
+
+ assert(length > 0);
+
+ if (text[length - 1] == '.')
+ {
+ /**
+ * Si le contenu à analyser se termine par un point, la position finale
+ * de ce point est prise en compte. Pour ce faire, le marqueur "$" des
+ * expressions régulières est sollicité. Hors, ce dernier n'est reconnu
+ * que pour le caractère "\n" terminant une ligne.
+ *
+ * On l'ajoute donc artificiellement.
+ */
+
+ real_length = length + 1;
+
+ real_text = malloc(real_length);
+ memcpy(real_text, text, length);
+ real_text[length] = '\n';
+
+ }
+ else
+ {
+ real_text = (char *)text;
+ real_length = length;
+ }
+
+ state = kaitai__scan_bytes(real_text, real_length, lexstate);
+
+ if (text[length - 1] == '.')
+ free(real_text);
+
+ status = yyparse(lexstate, locals, out);
+
+ result = (status == EXIT_SUCCESS);
+
+ yy_delete_buffer(state, lexstate);
+
+ kaitai_lex_destroy(lexstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* out = valeur générique résultante. [OUT] *
+* *
+* Description : Interprète une expression en une valeur quelconque. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_any(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+ bool result; /* Bilan à renvoyer */
+
+ result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+ return result;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : in_out = expression résolue traitée. [OUT] *
+* *
+* Description : Traduit les éventuels champs impliqués dans une expression. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool reduce_resolved_kaitai_expression(resolved_value_t *in_out)
+{
+ bool result; /* Bilan à renvoyer */
+ resolved_value_t deeper; /* Précision supplémentaire */
+
+ result = true;
+
+ while (result && in_out->type == GVT_RECORD)
+ {
+ 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);
+
+ else
+ break;
+
+ if (result)
+ {
+ EXIT_RESOLVED_VALUE(*in_out);
+ *in_out = deeper;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* out = valeur entière résultante. [OUT] *
+* *
+* Description : Interprète une expression en valeur ciblée entière. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_integer(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+ bool result; /* Bilan à renvoyer */
+
+ result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+ if (result)
+ result = reduce_resolved_kaitai_expression(out);
+
+ if (result)
+ result = (out->type == GVT_UNSIGNED_INTEGER || out->type == GVT_SIGNED_INTEGER);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* out = valeur booléenne résultante. [OUT] *
+* *
+* Description : Interprète une expression en valeur ciblée booléenne. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+ bool result; /* Bilan à renvoyer */
+
+ result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+ if (result)
+ result = reduce_resolved_kaitai_expression(out);
+
+ if (result)
+ {
+ if (out->type == GVT_UNSIGNED_INTEGER)
+ {
+ out->status = (out->unsigned_integer != 0);
+ out->type = GVT_BOOLEAN;
+ }
+ else if (out->type == GVT_SIGNED_INTEGER)
+ {
+ out->status = (out->signed_integer != 0);
+ out->type = GVT_BOOLEAN;
+ }
+ else if (out->type == GVT_FLOAT)
+ {
+ out->status = (out->floating_number != 0);
+ out->type = GVT_BOOLEAN;
+ }
+
+ }
+
+ if (result && out->type != GVT_BOOLEAN)
+ {
+ EXIT_RESOLVED_VALUE(*out);
+ result = false;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* out = valeur booléenne résultante. [OUT] *
+* *
+* Description : Interprète une expression en série d'octets. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_bytes(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+ bool result; /* Bilan à renvoyer */
+ char ch; /* Caractère unique spécifié */
+ sized_string_t converted; /* Conversion finale ? */
+
+ result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+ if (result)
+ result = reduce_resolved_kaitai_expression(out);
+
+ if (result)
+ {
+ if (out->type == GVT_UNSIGNED_INTEGER)
+ {
+ ch = out->unsigned_integer;
+ result = (ch <= 0xff);
+
+ if (result)
+ {
+ EXIT_RESOLVED_VALUE(*out);
+
+ out->bytes.data = malloc(sizeof(char));
+ out->bytes.data[0] = ch;
+ out->bytes.len = 1;
+ out->type = GVT_BYTES;
+
+ }
+
+ }
+
+ else if (out->type == GVT_ARRAY)
+ {
+ result = g_kaitai_array_convert_to_bytes(out->array, &converted);
+
+ if (result)
+ {
+ EXIT_RESOLVED_VALUE(*out);
+
+ out->bytes = converted;
+ out->type = GVT_BYTES;
+
+ }
+
+ }
+
+ }
+
+ if (result && out->type != GVT_BYTES)
+ {
+ EXIT_RESOLVED_VALUE(*out);
+ result = false;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* stream = flux de données pour Kaitai résultant. [OUT] *
+* *
+* Description : Interprète une expression en flux de données pour Kaitai. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_stream(const kaitai_scope_t *locals, const char *text, size_t length, GKaitaiStream **stream)
+{
+ bool result; /* Bilan à renvoyer */
+ resolved_value_t out; /* Elément générique obtenu */
+
+ result = _resolve_kaitai_expression_as_any(locals, text, length, &out);
+
+ if (result)
+ {
+ assert(out.type == GVT_STREAM);
+ *stream = out.stream;
+ }
+ else
+ *stream = NULL;
+
+ return result;
+
+}
diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c
new file mode 100644
index 0000000..0412ff7
--- /dev/null
+++ b/plugins/kaitai/import.c
@@ -0,0 +1,300 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * import.c - localisation de fichiers de définitions externes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "import.h"
+
+
+#include <libgen.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <common/environment.h>
+#include <core/logs.h>
+
+
+
+/* Charge un type Kaitai à partir d'une définition voisine. */
+static GKaitaiType *import_relative_kaitai_definition(const char *, const char *);
+
+/* Charge un type Kaitai depuis un emplacement de $KSPATH. */
+static GKaitaiType *import_kaitai_definition_from_env(const char *);
+
+/* Charge un interpréteur pour une définition voisine. */
+static GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *);
+
+/* Charge un interpréteur depuis un emplacement de $KSPATH. */
+static GKaitaiStruct *load_kaitai_definition_from_env(const char *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Charge un type Kaitai à partir d'une définition voisine. *
+* *
+* Retour : Type valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiType *import_relative_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiType *result; /* Structure chargée à renvoyer*/
+ char *tmp; /* Zone de travail temporaire */
+ char *base; /* Base de recherche */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ tmp = strdup(reference);
+ base = dirname(tmp);
+
+ ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target);
+ if (ret == -1) goto build_error;
+
+ result = g_kaitai_type_new_as_import(target, filename);
+
+ free(filename);
+
+ build_error:
+
+ free(tmp);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* *
+* Description : Charge un type Kaitai depuis un emplacement de $KSPATH. *
+* *
+* Retour : Type valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiType *import_kaitai_definition_from_env(const char *target)
+{
+ GKaitaiType *result; /* Structure chargée à renvoyer*/
+ char *paths; /* Emplacements de greffons */
+ char *save; /* Sauvegarde pour ré-entrance */
+ char *path; /* Chemin à fouiller */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ paths = get_env_var("KSPATH");
+
+ save = NULL; /* gcc... */
+
+ for (path = strtok_r(paths, ":", &save);
+ path != NULL;
+ path = strtok_r(NULL, ":", &save))
+ {
+ ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
+
+ result = g_kaitai_type_new_as_import(target, filename);
+
+ if (result != NULL)
+ log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition to import: %s"), filename);
+
+ free(filename);
+
+ }
+
+ free(paths);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Met en place un type Kaitai pour une définition désignée. *
+* *
+* Retour : Type valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiType *import_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiType *result; /* Structure chargée à renvoyer*/
+
+ result = NULL;
+
+ if (reference != NULL)
+ result = import_relative_kaitai_definition(target, reference);
+
+ if (result == NULL)
+ result = import_kaitai_definition_from_env(target);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Charge un interpréteur pour une définition voisine. *
+* *
+* Retour : Interprétateur valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiStruct *result; /* Structure chargée à renvoyer*/
+ char *tmp; /* Zone de travail temporaire */
+ char *base; /* Base de recherche */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ tmp = strdup(reference);
+ base = dirname(tmp);
+
+ ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target);
+ if (ret == -1) goto build_error;
+
+ result = g_kaitai_structure_new_from_file(filename);
+
+ free(filename);
+
+ build_error:
+
+ free(tmp);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* *
+* Description : Charge un interpréteur depuis un emplacement de $KSPATH. *
+* *
+* Retour : Interprétateur valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiStruct *load_kaitai_definition_from_env(const char *target)
+{
+ GKaitaiStruct *result; /* Structure chargée à renvoyer*/
+ char *paths; /* Emplacements de greffons */
+ char *save; /* Sauvegarde pour ré-entrance */
+ char *path; /* Chemin à fouiller */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ paths = get_env_var("KSPATH");
+
+ save = NULL; /* gcc... */
+
+ for (path = strtok_r(paths, ":", &save);
+ path != NULL;
+ path = strtok_r(NULL, ":", &save))
+ {
+ ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
+
+ result = g_kaitai_structure_new_from_file(filename);
+
+ if (result != NULL)
+ log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition: %s"), filename);
+
+ free(filename);
+
+ }
+
+ free(paths);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Met en place un interpréteur pour une définition désignée. *
+* *
+* Retour : Interprétateur valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiStruct *load_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiStruct *result; /* Structure chargée à renvoyer*/
+
+ result = NULL;
+
+ if (reference != NULL)
+ result = load_relative_kaitai_definition(target, reference);
+
+ if (result == NULL)
+ result = load_kaitai_definition_from_env(target);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h
new file mode 100644
index 0000000..66a0f5a
--- /dev/null
+++ b/plugins/kaitai/import.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * import.h - prototypes pour la localisation de fichiers de définitions externes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_IMPORT_H
+#define _PLUGINS_KAITAI_IMPORT_H
+
+
+#include "parsers/struct.h"
+#include "parsers/type.h"
+
+
+
+/* Met en place un type Kaitai pour une définition désignée. */
+GKaitaiType *import_kaitai_definition(const char *, const char *);
+
+/* Met en place un interpréteur pour une définition désignée. */
+GKaitaiStruct *load_kaitai_definition(const char *, const char *);
+
+
+
+#endif /* _PLUGINS_KAITAI_IMPORT_H */
diff --git a/plugins/kaitai/parser-int.h b/plugins/kaitai/parser-int.h
new file mode 100644
index 0000000..8bac523
--- /dev/null
+++ b/plugins/kaitai/parser-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser-int.h - prototypes pour les spécifications internes d'un lecteur Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_PARSER_INT_H
+#define PLUGINS_KAITAI_PARSER_INT_H
+
+
+#include "parser.h"
+
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
+
+
+
+/* Spécification d'un lecteur Kaitai (instance) */
+struct _GKaitaiParser
+{
+ GObject parent; /* A laisser en premier */
+
+};
+
+/* Spécification d'un lecteur Kaitai (classe) */
+struct _GKaitaiParserClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ parse_kaitai_fc parse; /* Phase d'analyse de contenu */
+
+};
+
+
+
+#endif /* PLUGINS_KAITAI_PARSER_INT_H */
diff --git a/plugins/kaitai/parser.c b/plugins/kaitai/parser.c
new file mode 100644
index 0000000..cfe1aa1
--- /dev/null
+++ b/plugins/kaitai/parser.c
@@ -0,0 +1,166 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - spécification d'un lecteur Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "parser.h"
+
+
+#include <assert.h>
+
+
+#include "parser-int.h"
+
+
+
+/* Initialise la classe des lecteurs de spécification Kaitai. */
+static void g_kaitai_parser_class_init(GKaitaiParserClass *);
+
+/* Initialise un lecteur de spécification Kaitai. */
+static void g_kaitai_parser_init(GKaitaiParser *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_parser_dispose(GKaitaiParser *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_parser_finalize(GKaitaiParser *);
+
+
+
+/* Indique le type défini pour un lecteur de spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiParser, g_kaitai_parser, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des lecteurs de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_parser_class_init(GKaitaiParserClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_parser_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_parser_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parser = instance à initialiser. *
+* *
+* Description : Initialise un lecteur de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_parser_init(GKaitaiParser *parser)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parser = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_parser_dispose(GKaitaiParser *parser)
+{
+ G_OBJECT_CLASS(g_kaitai_parser_parent_class)->dispose(G_OBJECT(parser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parser = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_parser_finalize(GKaitaiParser *parser)
+{
+ G_OBJECT_CLASS(g_kaitai_parser_parent_class)->finalize(G_OBJECT(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. *
+* 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 : - *
+* *
+******************************************************************************/
+
+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, epos, record);
+
+ 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
new file mode 100644
index 0000000..64d759d
--- /dev/null
+++ b/plugins/kaitai/parser.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - prototypes pour la spécification d'un lecteur Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_PARSER_H
+#define PLUGINS_KAITAI_PARSER_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+
+
+#include "record.h"
+#include "scope.h"
+
+
+
+#define G_TYPE_KAITAI_PARSER g_kaitai_parser_get_type()
+#define G_KAITAI_PARSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_PARSER, GKaitaiParser))
+#define G_IS_KAITAI_PARSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_PARSER))
+#define G_KAITAI_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_PARSER, GKaitaiParserClass))
+#define G_IS_KAITAI_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_PARSER))
+#define G_KAITAI_PARSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_PARSER, GKaitaiParserClass))
+
+
+/* Spécification d'un lecteur Kaitai (instance) */
+typedef struct _GKaitaiParser GKaitaiParser;
+
+/* Spécification d'un lecteur Kaitai (classe) */
+typedef struct _GKaitaiParserClass GKaitaiParserClass;
+
+
+/* Indique le type défini pour un lecteur de spécification Kaitai. */
+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 *, ext_vmpa_t *, GMatchRecord **);
+
+
+
+#endif /* PLUGINS_KAITAI_PARSER_H */
diff --git a/plugins/kaitai/parsers/Makefile.am b/plugins/kaitai/parsers/Makefile.am
new file mode 100644
index 0000000..c7e313b
--- /dev/null
+++ b/plugins/kaitai/parsers/Makefile.am
@@ -0,0 +1,25 @@
+
+noinst_LTLIBRARIES = libkaitaiparsers.la
+
+libkaitaiparsers_la_SOURCES = \
+ attribute-int.h \
+ attribute.h attribute.c \
+ enum-int.h \
+ enum.h enum.c \
+ instance-int.h \
+ instance.h instance.c \
+ meta-int.h \
+ meta.h meta.c \
+ struct-int.h \
+ struct.h struct.c \
+ switch-int.h \
+ switch.h switch.c \
+ type-int.h \
+ type.h type.c
+
+libkaitaiparsers_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaiparsers_la_SOURCES:%c=)
diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h
new file mode 100644
index 0000000..7d37af3
--- /dev/null
+++ b/plugins/kaitai/parsers/attribute-int.h
@@ -0,0 +1,107 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute-int.h - prototypes pour les spécifications internes d'un attribut Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_INT_H
+#define _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_INT_H
+
+
+#include "attribute.h"
+#include "switch.h"
+#include "../parser-int.h"
+
+
+
+/* Indique l'étiquette à utiliser pour identifier un attribut. */
+typedef const char * (* get_attribute_label_fc) (const GKaitaiAttribute *);
+
+/* Spécification d'un attribut Kaitai (instance) */
+struct _GKaitaiAttribute
+{
+ GKaitaiParser parent; /* A laisser en premier */
+
+ char *raw_id; /* Identifiant Kaitai */
+ char *orig_id; /* Identifiant humain */
+
+ char *doc; /* Eventuelle documentation */
+
+ KaitaiAttributePayload payload; /* Forme de la spécialisation */
+
+ struct
+ {
+ /* 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
+ {
+ BaseType basic; /* Type de base */
+
+ bool is_string; /* Renvoi vers une chaîne */
+
+ SourceEndian endian; /* Boutisme forcé ? */
+ bool has_endian; /* Présence de cette force */
+
+ };
+
+ /* KAP_USER_TYPE */
+ char *named_type; /* Type particulier */
+
+ /* KAP_DYNAMIC_TYPE */
+ GKaitaiSwitch *switchon; /* Détermination dynamique */
+
+ };
+
+ /* KAP_SIZED */
+ char *fixed_size; /* Taille déterminée */
+
+ KaitaiAttributeRepetition repetition; /* Forme de répétition */
+ char *repeat_controller; /* Indication sur la répétition*/
+
+ char *condition; /* Condition de chargement */
+
+ sized_string_t terminator; /* Marqueur de fin éventuel */
+ bool consume; /* Consommation dans le flux */
+ bool include; /* Intégration de ce marqueur */
+ bool eos_error; /* Gestion des erreurs en bout */
+
+};
+
+/* Spécification d'un attribut Kaitai (classe) */
+struct _GKaitaiAttributeClass
+{
+ GKaitaiParserClass parent; /* A laisser en premier */
+
+ get_attribute_label_fc get_label; /* Désignation d'une étiquette */
+
+};
+
+
+/* Met en place un lecteur d'attribut Kaitai. */
+bool g_kaitai_attribute_create(GKaitaiAttribute *, GYamlNode *, bool);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_INT_H */
diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c
new file mode 100644
index 0000000..6050bb1
--- /dev/null
+++ b/plugins/kaitai/parsers/attribute.c
@@ -0,0 +1,2213 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.c - spécification d'un attribut Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "attribute.h"
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <analysis/contents/restricted.h>
+#include <plugins/yaml/pair.h>
+
+
+#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"
+
+
+
+/* -------------------- CORRESPONDANCE ENTRE ATTRIBUT ET BINAIRE -------------------- */
+
+
+/* Initialise la classe des attributs de spécification Kaitai. */
+static void g_kaitai_attribute_class_init(GKaitaiAttributeClass *);
+
+/* Initialise un attribut de spécification Kaitai. */
+static void g_kaitai_attribute_init(GKaitaiAttribute *);
+
+/* Supprime toutes les références externes. */
+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 *);
+
+/* Valide la cohérence des informations portées par l'attribut. */
+static bool g_kaitai_attribute_check(const GKaitaiAttribute *);
+
+/* Copie le coeur de la définition d'un lecteur d'attribut. */
+static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+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 **);
+
+/* Détermine la zone de couverture finale d'une correspondance. */
+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 *, ext_vmpa_t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CORRESPONDANCE ENTRE ATTRIBUT ET BINAIRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un attribut de la spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiAttribute, g_kaitai_attribute, G_TYPE_KAITAI_PARSER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des attributs de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_attribute_class_init(GKaitaiAttributeClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GKaitaiParserClass *parser; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_attribute_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_attribute_finalize;
+
+ parser = G_KAITAI_PARSER_CLASS(klass);
+
+ parser->parse = (parse_kaitai_fc)g_kaitai_attribute_parse_content;
+
+ klass->get_label = g_kaitai_attribute_get_raw_id;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = instance à initialiser. *
+* *
+* Description : Initialise un attribut de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_attribute_init(GKaitaiAttribute *attrib)
+{
+ attrib->raw_id = NULL;
+ attrib->orig_id = NULL;
+
+ attrib->doc = NULL;
+
+ attrib->payload = KAP_UNINITIALIZED;
+
+ attrib->repetition = KAR_NO_REPETITION;
+ attrib->repeat_controller = NULL;
+
+ attrib->condition = NULL;
+
+ init_szstr(&attrib->terminator);
+ attrib->consume = true;
+ attrib->include = false;
+ attrib->eos_error = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_attribute_dispose(GKaitaiAttribute *attrib)
+{
+ if (attrib->payload & KAP_DYNAMIC_TYPE)
+ g_clear_object(&attrib->switchon);
+
+ G_OBJECT_CLASS(g_kaitai_attribute_parent_class)->dispose(G_OBJECT(attrib));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_attribute_finalize(GKaitaiAttribute *attrib)
+{
+ if (attrib->raw_id != NULL)
+ free(attrib->raw_id);
+
+ if (attrib->orig_id != NULL)
+ free(attrib->orig_id);
+
+ if (attrib->doc != NULL)
+ free(attrib->doc);
+
+ if (attrib->payload & KAP_FIXED_CONTENT)
+ exit_szstr(&attrib->fixed_content);
+
+ else if (attrib->payload & KAP_USER_TYPE)
+ free(attrib->named_type);
+
+ if (attrib->fixed_size != NULL)
+ free(attrib->fixed_size);
+
+ if (attrib->repeat_controller != NULL)
+ free(attrib->repeat_controller);
+
+ if (attrib->condition != NULL)
+ free(attrib->condition);
+
+ exit_szstr(&attrib->terminator);
+
+ G_OBJECT_CLASS(g_kaitai_attribute_parent_class)->finalize(G_OBJECT(attrib));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = noeud Yaml contenant l'attribut à constituer. *
+* *
+* Description : Construit un lecteur d'attribut Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *parent)
+{
+ GKaitaiAttribute *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL);
+
+ if (!g_kaitai_attribute_create(result, parent, false /* TODO : REMME ? */))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à initialiser pleinement.*
+* parent = noeud Yaml contenant l'attribut à constituer. *
+* need_id = encadre la présence d'un champ "id". *
+* *
+* Description : Met en place un lecteur d'attribut Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool need_id)
+{
+ bool result; /* Bilan à retourner */
+ GYamlNode *node; /* Noeud particulier présent */
+ const char *value; /* Valeur Yaml particulière */
+ char *rebuilt_value; /* Valeur Yaml rassemblée */
+ kaitai_scope_t fake; /* Contexte de circonstance */
+ resolved_value_t bytes; /* Données brutes obtenues */
+ GYamlNode *other_node; /* Autre noeud nécessaire */
+
+ result = false;
+
+ /* Identifiant obligatoire */
+
+ node = g_yaml_node_find_first_by_path(parent, "/id");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+ if (value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_id;
+ }
+
+ attrib->raw_id = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ else if (need_id)
+ goto bad_id;
+
+ /* Identifiant facultatif */
+
+ node = g_yaml_node_find_first_by_path(parent, "/-orig-id");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+ if (value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_id;
+ }
+
+ attrib->orig_id = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Eventuelle documentation */
+
+ node = g_yaml_node_find_first_by_path(parent, "/doc");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+ if (value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_doc;
+ }
+
+ attrib->doc = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Champ contents */
+
+ node = g_yaml_node_find_first_by_path(parent, "/contents");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ rebuilt_value = g_yaml_pair_aggregate_value(G_YAML_PAIR(node));
+
+ if (rebuilt_value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_content;
+ }
+
+ fake.meta = NULL;
+ fake.root = NULL;
+ fake.parent = NULL;
+ fake.last = NULL;
+
+ if (!resolve_kaitai_expression_as_bytes(&fake, rebuilt_value, strlen(rebuilt_value), &bytes))
+ {
+ free(rebuilt_value);
+ g_object_unref(G_OBJECT(node));
+ goto bad_content;
+ }
+
+ free(rebuilt_value);
+
+ attrib->fixed_content = bytes.bytes;
+
+ g_object_unref(G_OBJECT(node));
+
+ attrib->payload |= KAP_FIXED_CONTENT;
+
+ }
+
+ /* Charge portée par un type */
+
+ node = g_yaml_node_find_first_by_path(parent, "/type");
+
+ if (node != NULL)
+ {
+ if (attrib->payload & KAP_FIXED_CONTENT)
+ {
+ printf("Can not handle fixed content and type definition at the same time for an attribute.\n");
+ goto bad_definition;
+ }
+
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ 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
+ {
+ attrib->named_type = strdup(value);
+ attrib->payload |= KAP_USER_TYPE;
+ }
+
+ }
+
+ else
+ {
+ attrib->switchon = g_kaitai_switch_new(parent, attrib);
+ if (attrib->switchon == NULL) goto bad_definition;
+
+ attrib->payload |= KAP_DYNAMIC_TYPE;
+
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Répétitions contrôlées ? */
+
+ node = g_yaml_node_find_first_by_path(parent, "/repeat");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ if (strcmp(value, "eos") == 0)
+ attrib->repetition = KAR_END_OF_STREAM;
+
+ else if (strcmp(value, "expr") == 0)
+ {
+ other_node = g_yaml_node_find_first_by_path(parent, "/repeat-expr");
+
+ if (other_node != NULL)
+ {
+ if (G_IS_YAML_PAIR(other_node))
+ {
+ value = g_yaml_pair_get_value(G_YAML_PAIR(other_node));
+
+ if (value != NULL)
+ {
+ attrib->repetition = KAR_EXPRESSION;
+ attrib->repeat_controller = strdup(value);
+ }
+ else
+ printf("Expected repeat expression\n");
+
+ }
+
+ g_object_unref(G_OBJECT(other_node));
+
+ }
+
+ }
+
+ else if (strcmp(value, "until") == 0)
+ {
+ other_node = g_yaml_node_find_first_by_path(parent, "/repeat-until");
+
+ if (other_node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(other_node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(other_node));
+
+ if (value != NULL)
+ {
+ attrib->repetition = KAR_UNTIL;
+ attrib->repeat_controller = strdup(value);
+ }
+ else
+ printf("Expected repeat expression\n");
+
+ }
+
+ g_object_unref(G_OBJECT(other_node));
+
+ }
+
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Intégration sous condition ? */
+
+ node = g_yaml_node_find_first_by_path(parent, "/if");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ attrib->condition = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Taille fixée ? */
+
+ node = g_yaml_node_find_first_by_path(parent, "/size");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ attrib->fixed_size = strdup(value);
+ attrib->payload |= KAP_SIZED;
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ if ((attrib->payload & KAP_SIZED) == 0)
+ goto bad_content;
+
+ }
+
+ /* Prise en considération d'une taille maximale */
+
+ node = g_yaml_node_find_first_by_path(parent, "/size-eos");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL && strcmp(value, "true") == 0)
+ {
+ if (attrib->payload != KAP_UNINITIALIZED)
+ /* printf warning */;
+
+ attrib->payload |= KAP_SIZED_EOS;
+
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Champ terminator */
+
+ node = g_yaml_node_find_first_by_path(parent, "/terminator");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ rebuilt_value = g_yaml_pair_aggregate_value(G_YAML_PAIR(node));
+
+ if (rebuilt_value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_content;
+ }
+
+ fake.meta = NULL;
+ fake.root = NULL;
+ fake.parent = NULL;
+ fake.last = NULL;
+
+ if (!resolve_kaitai_expression_as_bytes(&fake, rebuilt_value, strlen(rebuilt_value), &bytes))
+ {
+ free(rebuilt_value);
+ g_object_unref(G_OBJECT(node));
+ goto bad_content;
+ }
+
+ free(rebuilt_value);
+
+ if (attrib->terminator.data != NULL)
+ printf("A ending content has already been specified (implicitly by the strz type)");
+
+ else
+ {
+ attrib->terminator.data = bytes.bytes.data;
+ attrib->terminator.len = bytes.bytes.len;
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Champ consume */
+
+ node = g_yaml_node_find_first_by_path(parent, "/consume");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ if (strcmp(value, "true") == 0)
+ attrib->consume = true;
+
+ else if (strcmp(value, "false") == 0)
+ attrib->consume = false;
+
+ else
+ printf("Unsupported value for the 'consume' property (expecting true of false)");
+
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Champ include */
+
+ node = g_yaml_node_find_first_by_path(parent, "/include");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ if (strcmp(value, "true") == 0)
+ attrib->include = true;
+
+ else if (strcmp(value, "false") == 0)
+ attrib->include = false;
+
+ else
+ printf("Unsupported value for the 'include' property (expecting true of false)");
+
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Champ eos-error */
+
+ node = g_yaml_node_find_first_by_path(parent, "/eos-error");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ if (strcmp(value, "true") == 0)
+ attrib->eos_error = true;
+
+ if (strcmp(value, "false") == 0)
+ attrib->eos_error = false;
+
+ else
+ printf("Unsupported value for the 'eos_error' property (expecting true of false)");
+
+ }
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Validation finale */
+
+ result = g_kaitai_attribute_check(attrib);
+
+ bad_definition:
+
+ bad_doc:
+ bad_id:
+ bad_content:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *attrib, const char *desc)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ attrib->basic = BTP_INVALID;
+ attrib->has_endian = false;
+
+ /**
+ * Cf. définition des types de base existants :
+ * http://doc.kaitai.io/user_guide.html#_fixed_size_structures
+ */
+
+#define RESOLVE_ENDIAN \
+ if (desc[2] == 'l') \
+ { \
+ if (desc[3] == 'e') \
+ { \
+ attrib->endian = SRE_LITTLE; \
+ attrib->has_endian = true; \
+ } \
+ } \
+ else if (desc[2] == 'b') \
+ { \
+ if (desc[3] == 'e') \
+ { \
+ attrib->endian = SRE_BIG; \
+ attrib->has_endian = true; \
+ } \
+ } \
+
+ /* Analyse de la chaîne fournie */
+
+ switch (desc[0])
+ {
+ case 'f':
+ switch (desc[1])
+ {
+ case '4':
+ attrib->basic = BTP_754R_32;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '8':
+ attrib->basic = BTP_754R_64;
+ RESOLVE_ENDIAN;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+ break;
+
+ case 's':
+ switch (desc[1])
+ {
+ case '1':
+ attrib->basic = BTP_CHAR;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '2':
+ attrib->basic = BTP_SHORT;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '4':
+ attrib->basic = BTP_INT;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '8':
+ attrib->basic = BTP_LONG_LONG;
+ RESOLVE_ENDIAN;
+ break;
+
+ case 't':
+ if (desc[2] == 'r')
+ {
+ attrib->basic = BTP_CHAR;
+ attrib->is_string = true;
+ if (desc[3] == 'z')
+ {
+ attrib->terminator.data = strdup("");
+ attrib->terminator.len = 1;
+ }
+ }
+ else
+ result = false;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+ break;
+
+ case 'u':
+ switch (desc[1])
+ {
+ case '1':
+ attrib->basic = BTP_UCHAR;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '2':
+ attrib->basic = BTP_USHORT;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '4':
+ attrib->basic = BTP_UINT;
+ RESOLVE_ENDIAN;
+ break;
+
+ case '8':
+ attrib->basic = BTP_ULONG_LONG;
+ RESOLVE_ENDIAN;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ /* Vérification d'une comparaison complète */
+ if (result)
+ switch (attrib->basic)
+ {
+ case BTP_CHAR:
+ if (attrib->is_string)
+ {
+ if (attrib->terminator.data != NULL)
+ result = (desc[4] == 0);
+ else
+ result = (desc[3] == 0);
+ }
+ else
+ {
+ if (attrib->has_endian)
+ result = (desc[4] == 0);
+ else
+ result = (desc[2] == 0);
+ }
+ break;
+
+ default:
+ if (attrib->has_endian)
+ result = (desc[4] == 0);
+ else
+ result = (desc[2] == 0);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = attribut Kaitai à valider. *
+* *
+* Description : Valide la cohérence des informations portées par l'attribut. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ /**
+ * Une lecture de tous les octets restants ne doit correspondre qu'à des octets bruts.
+ */
+ if (attrib->payload & KAP_SIZED_EOS && attrib->payload != KAP_SIZED_EOS)
+ {
+ result = (attrib->payload & KAP_BASIC_TYPE) && attrib->is_string;
+
+ if (!result)
+ {
+ printf("Reading all the remaining bytes should only produce bytes.");
+ result = true;
+ }
+
+ }
+
+ /**
+ * Une chaîne (type str[z]) doit comporter une séquence de terminaison.
+ */
+ if ((attrib->payload & KAP_BASIC_TYPE) && attrib->is_string)
+ {
+ result = (attrib->terminator.data != NULL) || (attrib->payload & (KAP_SIZED | KAP_SIZED_EOS));
+
+ if (!result)
+ {
+ printf("An unsized string (str type with no size attribute) has to be link to a terminator sequence.");
+ goto exit;
+ }
+
+ }
+
+ /**
+ * 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).
+ */
+ if (attrib->terminator.data != NULL)
+ {
+ result = ((attrib->payload & ~(KAP_FIXED_CONTENT | KAP_BASIC_TYPE | KAP_SIZED)) == 0);
+
+ if (result && (attrib->payload & KAP_BASIC_TYPE))
+ result = attrib->is_string;
+
+ if (!result)
+ {
+ printf("A useless terminator is specified.");
+ result = true;
+ goto exit;
+ }
+
+ }
+
+ /**
+ * Il n'est pas possible d'inclure un marqueur de fin sans le consommer.
+ */
+ if (!attrib->consume && attrib->include)
+ {
+ result = false;
+ printf("It is not possible to include a terminator without consuming it.");
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à dupliquer. *
+* type = type utilisateur à associer au nouvel attribut. *
+* *
+* Description : Dérive un lecteur d'attribut Kaitai pour un type utilisateur.*
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiAttribute *g_kaitai_attribute_dup_for_user_type(const GKaitaiAttribute *attrib, const char *type)
+{
+ GKaitaiAttribute *result; /* Structure à retourner */
+
+ result = g_kaitai_attribute_dup_for(attrib);
+
+ result->payload = KAP_USER_TYPE;
+
+ result->named_type = strdup(type);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à dupliquer. *
+* *
+* Description : Copie le coeur de la définition d'un lecteur d'attribut. *
+* *
+* Retour : Nouvelle instance à compléter. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *attrib)
+{
+ GKaitaiAttribute *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL);
+
+ /**
+ * Il n'y a rien à copier dans la structure parente.
+ *
+ * Les travaux de copie ne portent ainsi que sur le présent attribut.
+ */
+
+ if (attrib->raw_id != NULL)
+ result->raw_id = strdup(attrib->raw_id);
+
+ if (attrib->orig_id != NULL)
+ result->orig_id = strdup(attrib->orig_id);
+
+ if (attrib->doc != NULL)
+ result->doc = strdup(attrib->doc);
+
+ if (attrib->fixed_size != NULL)
+ result->fixed_size = strdup(attrib->fixed_size);
+
+ result->repetition = attrib->repetition;
+
+ if (attrib->repeat_controller != NULL)
+ result->repeat_controller = strdup(attrib->repeat_controller);
+
+ if (attrib->condition != NULL)
+ result->condition = strdup(attrib->condition);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* *
+* Description : Indique l'étiquette à utiliser pour identifier un attribut. *
+* *
+* Retour : Valeur brute de l'identifiant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_label(const GKaitaiAttribute *attrib)
+{
+ const char *result; /* Valeur à renvoyer */
+ GKaitaiAttributeClass *class; /* Classe de l'instance */
+
+ class = G_KAITAI_ATTRIBUTE_GET_CLASS(attrib);
+
+ result = class->get_label(attrib);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* *
+* Description : Indique la désignation brute d'un identifiant Kaitai. *
+* *
+* Retour : Valeur brute de l'identifiant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_raw_id(const GKaitaiAttribute *attrib)
+{
+ char *result; /* Valeur à renvoyer */
+
+ result = attrib->raw_id;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* *
+* Description : Indique la désignation originelle d'un identifiant Kaitai. *
+* *
+* Retour : Valeur originelle de l'identifiant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_original_id(const GKaitaiAttribute *attrib)
+{
+ char *result; /* Valeur à renvoyer */
+
+ result = attrib->orig_id;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* *
+* Description : Fournit une éventuelle documentation concernant l'attribut. *
+* *
+* Retour : Description enregistrée ou NULL si absente. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_doc(const GKaitaiAttribute *attrib)
+{
+ char *result; /* Valeur à renvoyer */
+
+ result = attrib->doc;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* *
+* Description : Indique la nature de la charge représentée par l'attribut. *
+* *
+* Retour : Forme de contenu représenté par le lecteur d'attribut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+KaitaiAttributePayload g_kaitai_attribute_get_payload(const GKaitaiAttribute *attrib)
+{
+ KaitaiAttributePayload result; /* Type de charge à renvoyer */
+
+ result = attrib->payload;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* basic = type de base Kaitai reconnu par le lecteur. [OUT]*
+* is_string = nature du type BTP_CHAR en sortie. [OUT] *
+* *
+* Description : Précise un éventuel type de base reconnu par le lecteur. *
+* *
+* Retour : Validité du type renseigné en argument. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_attribute_get_basic_type(const GKaitaiAttribute *attrib, BaseType *basic, bool *is_string)
+{
+ bool result; /* Validité à retourner */
+
+ result = (attrib->payload & KAP_BASIC_TYPE);
+
+ if (result)
+ {
+ *basic = attrib->basic;
+ *is_string = attrib->is_string;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* content = contenu binaire à venir lire. *
+* range = espace disponible pour la lecture. *
+* out = tableau d'octets retournés. [OUT] *
+* len = taille de ce tableau alloué. [OUT] *
+* *
+* Description : Lit les octets d'une chaîne représentée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_attribute_read_truncated_bytes(const GKaitaiAttribute *attrib, const GBinContent *content, const mrange_t *range, bin_t **out, size_t *len)
+{
+ bool result; /* Bilan à retourner */
+ vmpa2t tmppos; /* Localisation modifiable */
+ const bin_t *data; /* Accès aux données brutes */
+
+ result = false;
+
+ if ((attrib->payload & KAP_SIZED) == 0)
+ goto bad_type;
+
+ copy_vmpa(&tmppos, get_mrange_addr(range));
+
+ *len = get_mrange_length(range);
+
+ data = g_binary_content_get_raw_access(content, &tmppos, *len);
+
+ *out = malloc(sizeof(bin_t) * (*len + 1));
+
+ memcpy(*out, data, *len);
+ (*out)[*len] = '\0';
+
+ result = true;
+
+ bad_type:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* *
+* Description : Détermine si l'attribue porte une valeur entière signée. *
+* *
+* Retour : Bilan de la consultation : true si un entier signé est visé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *attrib)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if ((attrib->payload & KAP_BASIC_TYPE) == 0)
+ goto bad_type;
+
+ switch (attrib->basic)
+ {
+ case BTP_CHAR:
+ case BTP_SHORT:
+ case BTP_INT:
+ case BTP_LONG_LONG:
+ result = true;
+ break;
+
+ default:
+ break;
+
+ }
+
+ bad_type:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* content = contenu binaire à venir lire. *
+* range = espace de lecture. *
+* endian = boustime des données à respecter. *
+* 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_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinContent *content, const mrange_t *range, SourceEndian endian, resolved_value_t *out)
+{
+ bool result; /* Bilan à retourner */
+ vmpa2t tmppos; /* Localisation modifiable */
+ const bin_t *data; /* Données brutes restituées */
+ int8_t stmp8; /* Valeur de 8 bits lue */
+ uint8_t tmp8; /* Valeur de 8 bits lue */
+ int16_t stmp16; /* Valeur de 16 bits lue */
+ uint16_t tmp16; /* Valeur de 16 bits lue */
+ int32_t stmp32; /* Valeur de 32 bits lue */
+ uint32_t tmp32; /* Valeur de 32 bits lue */
+ int64_t stmp64; /* Valeur de 64 bits lue */
+ uint64_t tmp64; /* Valeur de 64 bits lue */
+
+ result = false;
+
+ if (attrib->payload & (KAP_FIXED_CONTENT | KAP_SIZED | KAP_SIZED_EOS))
+ {
+ copy_vmpa(&tmppos, get_mrange_addr(range));
+
+ data = g_binary_content_get_raw_access(content, &tmppos, get_mrange_length(range));
+ result = (data != NULL);
+
+ if (result)
+ {
+ out->type = GVT_BYTES;
+
+ out->bytes.len = get_mrange_length(range);
+
+ out->bytes.data = malloc(out->bytes.len);
+ memcpy(out->bytes.data, data, out->bytes.len);
+
+ }
+
+ }
+
+ else if (attrib->payload & KAP_BASIC_TYPE)
+ {
+ copy_vmpa(&tmppos, get_mrange_addr(range));
+
+ switch (attrib->basic)
+ {
+ case BTP_CHAR:
+ if (attrib->is_string)
+ {
+ copy_vmpa(&tmppos, get_mrange_addr(range));
+
+ data = g_binary_content_get_raw_access(content, &tmppos, get_mrange_length(range));
+ result = (data != NULL);
+
+ if (result)
+ {
+ out->type = GVT_BYTES;
+
+ out->bytes.len = get_mrange_length(range);
+
+ out->bytes.data = malloc(out->bytes.len);
+ memcpy(out->bytes.data, data, out->bytes.len);
+
+ }
+
+ }
+ else
+ {
+ assert(get_mrange_length(range) == 1);
+ result = g_binary_content_read_s8(content, &tmppos, &stmp8);
+ out->type = GVT_SIGNED_INTEGER;
+ out->signed_integer = stmp8;
+ }
+ break;
+
+ case BTP_UCHAR:
+ assert(get_mrange_length(range) == 1);
+ result = g_binary_content_read_u8(content, &tmppos, &tmp8);
+ out->type = GVT_UNSIGNED_INTEGER;
+ out->unsigned_integer = tmp8;
+ break;
+
+ case BTP_SHORT:
+ assert(get_mrange_length(range) == 2);
+ result = g_binary_content_read_s16(content, &tmppos, endian, &stmp16);
+ out->type = GVT_SIGNED_INTEGER;
+ out->signed_integer = stmp16;
+ break;
+
+ case BTP_USHORT:
+ assert(get_mrange_length(range) == 2);
+ result = g_binary_content_read_u16(content, &tmppos, endian, &tmp16);
+ out->type = GVT_UNSIGNED_INTEGER;
+ out->unsigned_integer = tmp16;
+ break;
+
+ case BTP_INT:
+ assert(get_mrange_length(range) == 4);
+ result = g_binary_content_read_s32(content, &tmppos, endian, &stmp32);
+ out->type = GVT_SIGNED_INTEGER;
+ out->signed_integer = stmp32;
+ break;
+
+ case BTP_UINT:
+ assert(get_mrange_length(range) == 4);
+ result = g_binary_content_read_u32(content, &tmppos, endian, &tmp32);
+ out->type = GVT_UNSIGNED_INTEGER;
+ out->unsigned_integer = tmp32;
+ break;
+
+ case BTP_LONG_LONG:
+ assert(get_mrange_length(range) == 8);
+ result = g_binary_content_read_s64(content, &tmppos, endian, &stmp64);
+ out->type = GVT_SIGNED_INTEGER;
+ out->signed_integer = stmp64;
+ break;
+
+ case BTP_ULONG_LONG:
+ assert(get_mrange_length(range) == 8);
+ result = g_binary_content_read_u64(content, &tmppos, endian, &tmp64);
+ out->type = GVT_UNSIGNED_INTEGER;
+ out->unsigned_integer = tmp64;
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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. *
+* 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_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 */
+
+ mrange_t work_range; /* Définition de cette aire */
+ GBinContent *work_area; /* Aire de travail */
+ bool has_empty_size; /* Mémorise une taille nulle */
+
+
+ //unsigned long long value; /* Valeur entière finale */
+ //bool status; /* Bilan d'une conversion */
+
+
+ vmpa2t tmp; /* Position de travail */
+ phys_t diff; /* Différentiel de positions */
+ resolved_value_t resolved; /* Valeur entière obtenue */
+ phys_t max_size; /* Taille maximale imposée */
+
+
+ const bin_t *data; /* Données à comparer */
+ GKaitaiType *user_type; /* Définition particulière */
+
+
+ mrange_t range; /* Couverture appliquée */
+ SourceEndian endian; /* Boutisme à observer */
+ phys_t cur_diff; /* Avancée de lecture courante */
+
+
+ result = false;
+ *record = NULL;
+
+ /* Lecture soumise à condition ? */
+
+ if (attrib->condition != NULL)
+ {
+ result = resolve_kaitai_expression_as_boolean(locals,
+ attrib->condition,
+ strlen(attrib->condition),
+ &authorized);
+
+ if (!result || !authorized.status)
+ goto exit;
+
+ }
+
+ /* Zone de travail restreinte */
+
+ g_binary_content_compute_end_pos(content, &tmp);
+ diff = compute_vmpa_diff(&epos->base, &tmp);
+
+ if (epos->consumed_extra_bits > 0 && diff > 0)
+ diff--;
+
+ if (attrib->payload & KAP_SIZED)
+ {
+ result = resolve_kaitai_expression_as_integer(locals,
+ attrib->fixed_size,
+ strlen(attrib->fixed_size),
+ &resolved);
+
+ if (result)
+ {
+ if (resolved.type == GVT_UNSIGNED_INTEGER)
+ max_size = resolved.unsigned_integer;
+ else
+ {
+ assert(resolved.type == GVT_SIGNED_INTEGER);
+
+ if (resolved.signed_integer < 0)
+ result = false;
+ else
+ max_size = resolved.signed_integer;
+
+ }
+
+ if (result)
+ result = (diff >= max_size);
+
+ if (!result)
+ printf("Need more data!\n");
+
+ if (result && max_size < diff)
+ diff = max_size;
+
+ }
+
+ if (!result)
+ goto exit;
+
+ 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);
+
+ }
+ else
+ {
+ work_area = content;
+ has_empty_size = false;
+ }
+
+ /* Etablissement d'une zone de correspondance */
+
+ if (attrib->payload == KAP_UNINITIALIZED)
+ 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)
+ {
+ 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);
+
+ result = (memcmp(data, attrib->fixed_content.data, attrib->fixed_content.len) == 0);
+
+ if (result)
+ diff = attrib->fixed_content.len;
+
+ }
+
+ }
+
+ 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:
+ case BTP_UCHAR:
+ if (attrib->is_string)
+ {
+ if ((attrib->payload & KAP_SIZED) == 0)
+ result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals,
+ work_area, &epos->base, record);
+ }
+ else
+ {
+ result = (diff >= 1);
+ diff = 1;
+ }
+ break;
+
+ case BTP_SHORT:
+ case BTP_USHORT:
+ result = (diff >= 2);
+ diff = 2;
+ break;
+
+ case BTP_INT:
+ case BTP_UINT:
+ case BTP_754R_32:
+ result = (diff >= 4);
+ diff = 4;
+ break;
+
+ case BTP_LONG_LONG:
+ case BTP_ULONG_LONG:
+ case BTP_754R_64:
+ result = (diff >= 8);
+ diff = 8;
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ else if (attrib->payload & KAP_USER_TYPE)
+ {
+ user_type = find_sub_type(locals, attrib->named_type);
+
+ if (user_type != NULL)
+ {
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type),
+ locals, work_area, epos, record);
+
+ if (result)
+ /**
+ * Le type utilisateur dérive du type GKaitaiStruct, qui ne possède pas
+ * d'identifiant propre. La correspondance produite est ainsi nominalement
+ * anonyme, ce qui empêche toute résolution.
+ *
+ * Le rattachement de l'étiquette de l'attribut d'origine est donc forcée ici.
+ */
+ g_match_record_fix_creator(*record, G_KAITAI_PARSER(attrib));
+
+
+ g_object_unref(G_OBJECT(user_type));
+
+ }
+
+ }
+
+ else if (attrib->payload & KAP_DYNAMIC_TYPE)
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, epos, record);
+
+ else if (attrib->payload & KAP_SIZED)
+ {
+ /* Cas déjà traité en début de fonction */
+
+ }
+
+ /* Enregistrement de la correspondance */
+
+ 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
+ * (cf. "4.10.3. Repeat until condition is met")
+ */
+
+ /* if (diff > 0) */
+ {
+ 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, &epos->base));
+
+ else
+ {
+ if (attrib->has_endian)
+ endian = attrib->endian;
+ else
+ endian = g_kaitai_meta_get_endian(locals->meta);
+
+ *record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian));
+
+ if (*record != NULL)
+ advance_vmpa(&epos->base, diff);
+ else
+ result = false;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Libération de zone de travail restreinte ? */
+
+ if (attrib->payload & KAP_SIZED)
+ {
+ /* 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(&epos->base, max_size - cur_diff);
+
+ assert(work_area != content);
+ g_object_unref(G_OBJECT(work_area));
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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] *
+* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
+* *
+* Description : Extrait d'un contenu une série d'octets avec terminaison. *
+* *
+* Retour : Bilan de l'opératon : true pour continuer, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *attrib, const kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+ bool result; /* Bilan à retourner */
+ sized_string_t marker; /* Marqueur potentiel à tester */
+ vmpa2t iter; /* Tête de lecture courante */
+ vmpa2t end; /* Fin du parcours possible */
+ vmpa2t tmp; /* Position à mouvante */
+ phys_t diff; /* Avancée de lecture courante */
+ mrange_t range; /* Couverture appliquée */
+ SourceEndian endian; /* Boutisme à observer */
+
+ result = false;
+
+ /* Recherche du marqueur de fin */
+
+ marker.len = attrib->terminator.len;
+
+ copy_vmpa(&iter, pos);
+ g_binary_content_compute_end_pos(content, &end);
+
+ while (cmp_vmpa_by_phy(&iter, &end) < 0)
+ {
+ copy_vmpa(&tmp, &iter);
+
+ marker.data = (char *)g_binary_content_get_raw_access(content, &tmp, marker.len);
+ if (marker.data == NULL) break;
+
+ if (szmemcmp(&marker, &attrib->terminator) == 0)
+ {
+ result = true;
+ break;
+ }
+
+ advance_vmpa(&iter, 1);
+
+ }
+
+ /* Si la recherche a abouti */
+
+ if (result)
+ {
+ diff = compute_vmpa_diff(pos, &iter);
+
+ if (attrib->include)
+ diff += marker.len;
+
+ init_mrange(&range, pos, diff);
+
+ if (attrib->has_endian)
+ endian = attrib->endian;
+ else
+ endian = g_kaitai_meta_get_endian(locals->meta);
+
+ *record = G_MATCH_RECORD(g_record_item_new(attrib, content, &range, endian));
+
+ copy_vmpa(pos, &iter);
+
+ if (attrib->consume)
+ advance_vmpa(pos, marker.len);
+
+ }
+
+ /* Sinon l'absence de marqueur est-elle tolérée ? */
+
+ else if (!attrib->eos_error)
+ {
+ diff = compute_vmpa_diff(pos, &end);
+
+ init_mrange(&range, pos, diff);
+
+ if (attrib->has_endian)
+ endian = attrib->endian;
+ else
+ endian = g_kaitai_meta_get_endian(locals->meta);
+
+ *record = G_MATCH_RECORD(g_record_item_new(attrib, content, &range, endian));
+
+ copy_vmpa(pos, &end);
+
+ result = true;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* maxsize = taille maximale de la zone de correspondance. [OUT]*
+* range = zone de couverture à officialiser. [OUT] *
+* *
+* Description : Détermine la zone de couverture finale d'une correspondance. *
+* *
+* Retour : Bilan de l'opératon : true pour continuer, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *attrib, const kaitai_scope_t *locals, const GBinContent *content, const vmpa2t *pos, phys_t *maxsize, mrange_t *range)
+{
+ bool result; /* Bilan à retourner */
+ sized_string_t marker; /* Marqueur potentiel à tester */
+ vmpa2t iter; /* Tête de lecture courante */
+ vmpa2t end; /* Fin du parcours possible */
+ vmpa2t tmp; /* Position à mouvante */
+ phys_t diff; /* Avancée de lecture courante */
+
+ if (attrib->terminator.data == NULL)
+ {
+ init_mrange(range, pos, *maxsize);
+ result = true;
+ }
+
+ else
+ {
+ result = false;
+
+ if (attrib->terminator.len > *maxsize)
+ goto exit;
+
+ /* Recherche du marqueur de fin */
+
+ marker.len = attrib->terminator.len;
+
+ copy_vmpa(&iter, pos);
+
+ copy_vmpa(&tmp, pos);
+ advance_vmpa(&tmp, *maxsize - marker.len);
+
+ while (cmp_vmpa_by_phy(&iter, &end) <= 0)
+ {
+ copy_vmpa(&tmp, &iter);
+
+ marker.data = (char *)g_binary_content_get_raw_access(content, &tmp, marker.len);
+ if (marker.data == NULL) break;
+
+ if (szmemcmp(&marker, &attrib->terminator) == 0)
+ {
+ result = true;
+ break;
+ }
+
+ advance_vmpa(&iter, 1);
+
+ }
+
+ /* Si la recherche a abouti */
+
+ if (result)
+ {
+ diff = compute_vmpa_diff(pos, &iter);
+
+ if (attrib->include)
+ init_mrange(range, pos, diff + marker.len);
+ else
+ init_mrange(range, pos, diff);
+
+ assert((diff + marker.len) <= *maxsize);
+
+ if (attrib->consume)
+ *maxsize = diff + marker.len;
+ else
+ *maxsize = diff;
+
+ }
+
+ /* Sinon l'absence de marqueur est-elle tolérée ? */
+
+ else if (!attrib->eos_error)
+ {
+ init_mrange(range, pos, *maxsize);
+ result = true;
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* 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_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 */
+ GRecordList *list; /* Constitution d'une liste */
+ vmpa2t end; /* Position maximale du flux */
+ phys_t diff; /* Différentiel de positions */
+ GMatchRecord *child; /* Element de liste à intégrer */
+ resolved_value_t resolved; /* Valeur entière obtenue */
+ unsigned long long count; /* Nombre d'itérations à mener */
+ unsigned long long i; /* Boucle de parcours */
+ resolved_value_t loop; /* Poursuite des lectures ? */
+
+ if (attrib->repetition == KAR_NO_REPETITION)
+ result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, record);
+
+ else
+ {
+ /* Lecture soumise à condition ? */
+
+ if (attrib->condition != NULL)
+ {
+ result = resolve_kaitai_expression_as_boolean(locals,
+ attrib->condition,
+ strlen(attrib->condition),
+ &authorized);
+
+ if (!result || !authorized.status)
+ goto exit;
+
+ }
+
+ list = g_record_list_new(attrib, content, &epos->base);
+
+ switch (attrib->repetition)
+ {
+ case KAR_END_OF_STREAM:
+
+ result = true;
+
+ g_binary_content_compute_end_pos(content, &end);
+ diff = compute_vmpa_diff(&epos->base, &end);
+
+ while (diff > 0)
+ {
+ 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(&epos->base, &end);
+
+ }
+
+ break;
+
+ case KAR_EXPRESSION:
+
+ result = resolve_kaitai_expression_as_integer(locals,
+ attrib->repeat_controller,
+ strlen(attrib->repeat_controller),
+ &resolved);
+
+ if (resolved.type == GVT_UNSIGNED_INTEGER)
+ count = resolved.unsigned_integer;
+ else
+ {
+ assert(resolved.type == GVT_SIGNED_INTEGER);
+
+ if (resolved.signed_integer < 0)
+ {
+ result = false;
+ break;
+ }
+
+ count = resolved.signed_integer;
+
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ 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);
+
+ }
+
+ break;
+
+ case KAR_UNTIL:
+
+ do
+ {
+ 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);
+
+ result = resolve_kaitai_expression_as_boolean(locals,
+ attrib->repeat_controller,
+ strlen(attrib->repeat_controller),
+ &loop);
+ if (!result) break;
+
+ }
+ while (!loop.status);
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (!result) g_clear_object(&list);
+
+ *record = G_MATCH_RECORD(list);
+
+ }
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h
new file mode 100644
index 0000000..9b43936
--- /dev/null
+++ b/plugins/kaitai/parsers/attribute.h
@@ -0,0 +1,158 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.h - prototypes pour la spécification d'un attribut Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H
+#define _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+#include <analysis/types/basic.h>
+#include <plugins/yaml/node.h>
+
+
+#include "../expression.h"
+
+
+
+#define G_TYPE_KAITAI_ATTRIBUTE g_kaitai_attribute_get_type()
+#define G_KAITAI_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_ATTRIBUTE, GKaitaiAttribute))
+#define G_IS_KAITAI_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_ATTRIBUTE))
+#define G_KAITAI_ATTRIBUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_ATTRIBUTE, GKaitaiAttributeClass))
+#define G_IS_KAITAI_ATTRIBUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_ATTRIBUTE))
+#define G_KAITAI_ATTRIBUTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_ATTRIBUTE, GKaitaiAttributeClass))
+
+
+/* Spécification d'un attribut Kaitai (instance) */
+typedef struct _GKaitaiAttribute GKaitaiAttribute;
+
+/* Spécification d'un attribut Kaitai (classe) */
+typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass;
+
+
+/* Type de charge associée à un attribut */
+typedef enum _KaitaiAttributePayload
+{
+ KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */
+
+ 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 */ /* TODO : REMME ? (car non utilisé) */
+typedef enum _KaitaiBasicType
+{
+ KBT_U1, /* Octet non signé */
+ KBT_U2, /* Mot de 16 bits non signé */
+ KBT_U2LE, /* Mot de 16 bits non signé */
+ KBT_U2BE, /* Mot de 16 bits non signé */
+ KBT_U4, /* Mot de 32 bits non signé */
+ KBT_U4LE, /* Mot de 32 bits non signé */
+ KBT_U4BE, /* Mot de 32 bits non signé */
+ KBT_U8, /* Mot de 64 bits non signé */
+ KBT_U8LE, /* Mot de 64 bits non signé */
+ KBT_U8BE, /* Mot de 64 bits non signé */
+ KBT_S1, /* Octet signé */
+ KBT_S2, /* Mot de 16 bits signé */
+ KBT_S2LE, /* Mot de 16 bits signé */
+ KBT_S2BE, /* Mot de 16 bits signé */
+ KBT_S4, /* Mot de 32 bits signé */
+ KBT_S4LE, /* Mot de 32 bits signé */
+ KBT_S4BE, /* Mot de 32 bits signé */
+ KBT_S8, /* Mot de 64 bits signé */
+ KBT_S8LE, /* Mot de 64 bits signé */
+ KBT_S8BE, /* Mot de 64 bits signé */
+ KBT_F4, /* Flottant sur 32 bits */
+ KBT_F4BE, /* Flottant sur 32 bits */
+ KBT_F4LE, /* Flottant sur 32 bits */
+ KBT_F8, /* Flottant sur 64 bits */
+ KBT_F8BE, /* Flottant sur 64 bits */
+ KBT_F8LE, /* Flottant sur 64 bits */
+ KBT_STR, /* Chaîne de caractères */
+ KBT_STRZ, /* Chaîne de caractères + '\0' */
+
+} KaitaiBasicType;
+
+/* Formes de répétition d'une lecture d'attribut */
+typedef enum _KaitaiAttributeRepetition
+{
+ KAR_NO_REPETITION, /* Aucune forme de répétition */
+
+ KAR_END_OF_STREAM, /* Redites autant que possible */
+ KAR_EXPRESSION, /* Répétitions selon quantité */
+ KAR_UNTIL, /* Répétitions sous condition */
+
+} KaitaiAttributeRepetition;
+
+
+/* Indique le type défini pour un attribut de la spécification Kaitai. */
+GType g_kaitai_attribute_get_type(void);
+
+/* Construit un lecteur d'attribut Kaitai. */
+GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *);
+
+/* Dérive un lecteur d'attribut Kaitai pour un type utilisateur. */
+GKaitaiAttribute *g_kaitai_attribute_dup_for_user_type(const GKaitaiAttribute *, const char *);
+
+/* Indique l'étiquette à utiliser pour identifier un attribut. */
+const char *g_kaitai_attribute_get_label(const GKaitaiAttribute *);
+
+/* Indique la désignation brute d'un identifiant Kaitai. */
+const char *g_kaitai_attribute_get_raw_id(const GKaitaiAttribute *);
+
+/* Indique la désignation originelle d'un identifiant Kaitai. */
+const char *g_kaitai_attribute_get_original_id(const GKaitaiAttribute *);
+
+/* Fournit une éventuelle documentation concernant l'attribut. */
+const char *g_kaitai_attribute_get_doc(const GKaitaiAttribute *);
+
+/* Indique la nature de la charge représentée par l'attribut. */
+KaitaiAttributePayload g_kaitai_attribute_get_payload(const GKaitaiAttribute *);
+
+/* Précise un éventuel type de base reconnu par le lecteur. */
+bool g_kaitai_attribute_get_basic_type(const GKaitaiAttribute *, BaseType *, bool *);
+
+/* Lit les octets d'une chaîne représentée. */
+bool g_kaitai_attribute_read_truncated_bytes(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, bin_t **, size_t *);
+
+/* Détermine si l'attribue porte une valeur entière signée. */
+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/enum-int.h b/plugins/kaitai/parsers/enum-int.h
new file mode 100644
index 0000000..b62ae41
--- /dev/null
+++ b/plugins/kaitai/parsers/enum-int.h
@@ -0,0 +1,79 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum-int.h - prototypes internes pour la gestion des énumérations Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_PARSERS_ENUM_INT_H
+#define PLUGINS_KAITAI_PARSERS_ENUM_INT_H
+
+
+#include "enum.h"
+
+
+
+/* ------------------------- MANIPULATION D'UNE ENUMERATION ------------------------- */
+
+
+/* Mémorisation d'une valeur d'énumération */
+typedef struct _enum_value_t
+{
+ resolved_value_t value; /* Valeur entière représentée */
+ char *label; /* Elément associé à une valeur*/
+ char *doc; /* Eventuelle documentation */
+
+} enum_value_t;
+
+
+
+/* ----------------------- GESTION D'UN GROUPE D'ENUMERATIONS ----------------------- */
+
+
+/* Définition d'un ensemble d'énumérations Kaitai (instance) */
+struct _GKaitaiEnum
+{
+ GObject parent; /* A laisser en premier */
+
+ char *name; /* Désignation de l'énumération*/
+
+ enum_value_t **cases_v2l; /* Choix indexés par valeur */
+ size_t cases_v2l_count; /* Quantité de ces choix */
+
+ enum_value_t **cases_l2v; /* Choix indexés par étiquette */
+ size_t cases_l2v_count; /* Quantité de ces choix */
+
+ enum_value_t *defcase; /* Choix par défaut ou NULL */
+
+};
+
+/* Définition d'un ensemble d'énumérations Kaitai (classe) */
+struct _GKaitaiEnumClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un groupe d'énumérations Kaitai. */
+bool g_kaitai_enum_create(GKaitaiEnum *, GYamlNode *);
+
+
+
+#endif /* PLUGINS_KAITAI_PARSERS_ENUM_INT_H */
diff --git a/plugins/kaitai/parsers/enum.c b/plugins/kaitai/parsers/enum.c
new file mode 100644
index 0000000..27e5660
--- /dev/null
+++ b/plugins/kaitai/parsers/enum.c
@@ -0,0 +1,765 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - gestion des énumérations Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "enum.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include <common/extstr.h>
+#include <common/sort.h>
+#include <core/logs.h>
+#include <plugins/yaml/collection.h>
+#include <plugins/yaml/pair.h>
+
+
+#include "enum-int.h"
+
+
+
+/* ------------------------- MANIPULATION D'UNE ENUMERATION ------------------------- */
+
+
+/* Construit une valeur d'énumération à partir d'indications. */
+static enum_value_t *build_enum_value(GYamlNode *, bool *);
+
+/* Supprime de la mémoire une valeur d'énumération. */
+static void delete_enum_value(enum_value_t *);
+
+/* Etablit la comparaison entre deux valeurs d'énumération. */
+static int compare_enum_values_by_value(const enum_value_t **, const enum_value_t **);
+
+/* Etablit la comparaison entre deux noms d'énumération. */
+static int compare_enum_values_by_label(const enum_value_t **, const enum_value_t **);
+
+/* Etablit la comparaison entre deux noms d'énumération. */
+static int compare_enum_values_by_sized_label(const sized_string_t *, const enum_value_t **);
+
+
+
+/* ----------------------- GESTION D'UN GROUPE D'ENUMERATIONS ----------------------- */
+
+
+/* Initialise la classe des groupes d'énumérations Kaitai. */
+static void g_kaitai_enum_class_init(GKaitaiEnumClass *);
+
+/* Initialise un groupe d'énumérations Kaitai. */
+static void g_kaitai_enum_init(GKaitaiEnum *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_enum_dispose(GKaitaiEnum *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_enum_finalize(GKaitaiEnum *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATION D'UNE ENUMERATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud Yaml à venir lire. *
+* defcase = indique si une valeur par défaut est visée. [OUT] *
+* *
+* Description : Construit une valeur d'énumération à partir d'indications. *
+* *
+* Retour : Structure de valeur mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static enum_value_t *build_enum_value(GYamlNode *node, bool *defcase)
+{
+ enum_value_t *result; /* Valeur à retourner */
+ const char *key; /* Clef d'une énumération */
+ kaitai_scope_t fake; /* Contexte de circonstance */
+ resolved_value_t kval; /* Valeur à indexer */
+ const char *value; /* Valeur Yaml particulière */
+ char *path; /* Chemin d'accès suivant */
+ GYamlNode *children; /* Sous-noeuds rattachés */
+ GYamlNode *sub; /* Sous-noeud à considérer */
+
+ result = NULL;
+
+ *defcase = false;
+
+ if (!G_IS_YAML_PAIR(node))
+ goto bad_node;
+
+ /* Identification de la valeur énumérative */
+
+ key = g_yaml_pair_get_key(G_YAML_PAIR(node));
+
+ if (strcmp(key, "_") == 0)
+ {
+ /**
+ * Exemple de choix par défaut :
+ * http://doc.kaitai.io/user_guide.html#tlv
+ */
+
+ kval.type = GVT_UNSIGNED_INTEGER;
+ kval.unsigned_integer = ~0llu;
+
+ *defcase = true;
+
+ }
+
+ else
+ {
+ fake.meta = NULL;
+ fake.root = NULL;
+ fake.parent = NULL;
+ fake.last = NULL;
+
+ if (!resolve_kaitai_expression_as_integer(&fake, key, strlen(key), &kval))
+ goto bad_node;
+
+ }
+
+ /* Récupération des éléments associés à la valeur */
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value != NULL)
+ {
+ result = malloc(sizeof(enum_value_t));
+
+ result->value = kval;
+ result->label = strdup(value);
+ result->doc = NULL;
+
+ }
+ else
+ {
+ /**
+ * Les énumérations peuvent comporter un commentaire associé
+ * sous forme d'un élément de documentation complémentaire.
+ *
+ * Cf. http://doc.kaitai.io/user_guide.html#verbose-enums
+ */
+
+ asprintf(&path, "/%s/", key);
+ children = g_yaml_node_find_first_by_path(node, path);
+ free(path);
+
+ if (!G_IS_YAML_COLLEC(children))
+ goto bad_value;
+
+ /* Identifiant */
+
+ sub = g_yaml_node_find_first_by_path(children, "/id");
+
+ if (!G_IS_YAML_PAIR(sub))
+ goto bad_sub_value;
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(sub));
+
+ if (value == NULL)
+ goto bad_sub_value;
+
+ result = malloc(sizeof(enum_value_t));
+
+ result->value = kval;
+ result->label = strdup(value);
+ result->doc = NULL;
+
+ g_object_unref(G_OBJECT(sub));
+
+ /* Documentation */
+
+ sub = g_yaml_node_find_first_by_path(children, "/doc");
+
+ if (!G_IS_YAML_PAIR(sub))
+ goto bad_sub_value;
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(sub));
+
+ if (value == NULL)
+ goto bad_sub_value;
+
+ result->doc = strdup(value);
+
+ bad_sub_value:
+
+ g_clear_object(&sub);
+
+ g_object_unref(G_OBJECT(children));
+
+ bad_value:
+
+ ;
+
+ }
+
+ bad_node:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : value = valeur à traiter. *
+* *
+* Description : Supprime de la mémoire une valeur d'énumération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_enum_value(enum_value_t *value)
+{
+ EXIT_RESOLVED_VALUE(value->value);
+
+ free(value->label);
+
+ if (value->doc != NULL)
+ free(value->doc);
+
+ free(value);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premières informations à consulter. *
+* b = secondes informations à consulter. *
+* *
+* Description : Etablit la comparaison entre deux valeurs d'énumération. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compare_enum_values_by_value(const enum_value_t **a, const enum_value_t **b)
+{
+ int result; /* Bilan à retourner */
+ const resolved_value_t *value_a; /* Raccouri d'accès pour a */
+ const resolved_value_t *value_b; /* Raccouri d'accès pour b */
+
+ value_a = &(*a)->value;
+ value_b = &(*b)->value;
+
+ if (value_a->type == GVT_UNSIGNED_INTEGER && value_b->type == GVT_UNSIGNED_INTEGER)
+ result = sort_unsigned_long_long(value_a->unsigned_integer, value_b->unsigned_integer);
+
+ else if (value_a->type == GVT_UNSIGNED_INTEGER && value_b->type == GVT_UNSIGNED_INTEGER)
+ result = sort_signed_long_long(value_a->signed_integer, value_b->signed_integer);
+
+ else
+ {
+ /**
+ * Le code Python a deux options : soit fournir un équivalent à la
+ * structure resolved_value_t lors de l'appel correspondant à cette
+ * fonction compare_enum_values_by_value(), soit fournir un nombre
+ * directement.
+ *
+ * Comme PyArg_ParseTuple() est obligée de trancher entre non-signé
+ * et signé, le parti est pris de considérer le non-signé coté Python.
+ * On s'adapte en conséquence ici.
+ *
+ * La structure resolved_value_t est une union, donc les valeurs
+ * sont potientiellement au mauvais format mais bien présentes.
+ */
+
+ /**
+ * result = sort_unsigned_long_long(value_a->type, value_b->type);
+ */
+
+ result = sort_unsigned_long_long(value_a->unsigned_integer, value_b->unsigned_integer);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premières informations à consulter. *
+* b = secondes informations à consulter. *
+* *
+* Description : Etablit la comparaison entre deux noms d'énumération. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compare_enum_values_by_label(const enum_value_t **a, const enum_value_t **b)
+{
+ int result; /* Bilan à retourner */
+
+ result = strcmp((*a)->label, (*b)->label);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : l = premières informations à consulter. *
+* b = secondes informations à consulter. *
+* *
+* Description : Etablit la comparaison entre deux noms d'énumération. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compare_enum_values_by_sized_label(const sized_string_t *l, const enum_value_t **b)
+{
+ int result; /* Bilan à retourner */
+
+ result = strncmp(l->data, (*b)->label, l->len); // FIXME
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION D'UN GROUPE D'ENUMERATIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un ensemble d'énumérations Kaitai. */
+G_DEFINE_TYPE(GKaitaiEnum, g_kaitai_enum, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des groupes d'énumérations Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_enum_class_init(GKaitaiEnumClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_enum_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_enum_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = instance à initialiser. *
+* *
+* Description : Initialise un groupe d'énumérations Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_enum_init(GKaitaiEnum *kenum)
+{
+ kenum->name = NULL;
+
+ kenum->cases_v2l = NULL;
+ kenum->cases_v2l_count = 0;
+
+ kenum->cases_l2v = NULL;
+ kenum->cases_l2v_count = 0;
+
+ kenum->defcase = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_enum_dispose(GKaitaiEnum *kenum)
+{
+ G_OBJECT_CLASS(g_kaitai_enum_parent_class)->dispose(G_OBJECT(kenum));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_enum_finalize(GKaitaiEnum *kenum)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (kenum->name != NULL)
+ free(kenum->name);
+
+ for (i = 0; i < kenum->cases_v2l_count; i++)
+ delete_enum_value(kenum->cases_v2l[i]);
+
+ if (kenum->cases_v2l != NULL)
+ free(kenum->cases_v2l);
+
+ if (kenum->cases_l2v != NULL)
+ free(kenum->cases_l2v);
+
+ if (kenum->defcase != NULL)
+ delete_enum_value(kenum->defcase);
+
+ G_OBJECT_CLASS(g_kaitai_enum_parent_class)->finalize(G_OBJECT(kenum));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = noeud Yaml contenant l'attribut à constituer. *
+* *
+* Description : Construit un groupe d'énumérations Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiEnum *g_kaitai_enum_new(GYamlNode *parent)
+{
+ GKaitaiEnum *result; /* Identifiant à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_ENUM, NULL);
+
+ if (!g_kaitai_enum_create(result, parent))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = groupe d'énumérations à initialiser pleinement. *
+* parent = noeud Yaml contenant l'attribut à constituer. *
+* *
+* Description : Met en place un groupe d'énumérations Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_enum_create(GKaitaiEnum *kenum, GYamlNode *parent)
+{
+ bool result; /* Bilan à retourner */
+ char *path; /* Chemin des valeurs */
+ GYamlNode *collec; /* Liste de noeuds à traiter */
+ GYamlNode **nodes; /* Eventuels noeuds trouvés */
+ size_t count; /* Quantité de ces noeuds */
+ size_t i; /* Boucle de parcours */
+ bool defcase; /* Définition par défaut ? */
+ enum_value_t *value; /* Valeur énumérative nouvelle */
+ bool found; /* Présence de partage existant*/
+ size_t index; /* Indice du point d'insertion */
+
+ result = false;
+
+ /* Récupération du nom */
+
+ if (!G_IS_YAML_PAIR(parent)) goto exit;
+
+ kenum->name = strdup(g_yaml_pair_get_key(G_YAML_PAIR(parent)));
+
+ /* Association de valeurs */
+
+ path = strdup("/");
+ path = stradd(path, kenum->name);
+ path = stradd(path, "/");
+
+ collec = g_yaml_node_find_first_by_path(parent, path);
+
+ free(path);
+
+ if (collec != NULL)
+ {
+ if (G_IS_YAML_COLLEC(collec))
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+ else
+ count = 0;
+
+ if (count > 0)
+ {
+ for (i = 0; i < count; i++)
+ {
+ value = build_enum_value(nodes[i], &defcase);
+ if (value == NULL) break;
+
+ if (defcase)
+ {
+ if (kenum->defcase != NULL)
+ {
+ log_variadic_message(LMT_WARNING,
+ _("Multiple definition of the defaut value for the enumeration '%s'"),
+ kenum->name);
+
+ delete_enum_value(value);
+ break;
+
+ }
+
+ /**
+ * Exemple de choix par défaut :
+ * http://doc.kaitai.io/user_guide.html#tlv
+ */
+
+ kenum->defcase = value;
+
+ }
+
+ else
+ {
+ kenum->cases_v2l = qinsert(kenum->cases_v2l, &kenum->cases_v2l_count, sizeof(enum_value_t *),
+ (__compar_fn_t)compare_enum_values_by_value, &value);
+
+ found = bsearch_index(&value, kenum->cases_l2v, kenum->cases_l2v_count, sizeof(enum_value_t *),
+ (__compar_fn_t)compare_enum_values_by_label, &index);
+
+ if (found)
+ log_variadic_message(LMT_WARNING,
+ _("Multiple occurrence of the label %s in the enumeration '%s'"),
+ value->label, kenum->name);
+
+ else
+ kenum->cases_l2v = _qinsert(kenum->cases_l2v, &kenum->cases_l2v_count, sizeof(enum_value_t *),
+ &value, index);
+
+ }
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
+
+ result = (i == count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ free(nodes);
+
+ }
+
+ g_object_unref(G_OBJECT(collec));
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = groupe d'énumérations à consulter. *
+* *
+* Description : Fournit le nom principal d'une énumération. *
+* *
+* Retour : Désignation de l'énumération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_kaitai_enum_get_name(const GKaitaiEnum *kenum)
+{
+ const char *result; /* Chaîne à retourner */
+
+ result = kenum->name;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = groupe d'énumérations à consulter. *
+* label = étiquette de l'élément constant à traduire. *
+* value = valeur concrète correspondante. [OUT] *
+* *
+* Description : Traduit une étiquette brute en constante d'énumération. *
+* *
+* Retour : Bilan de la conversion. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_enum_find_value(const GKaitaiEnum *kenum, const sized_string_t *label, resolved_value_t *value)
+{
+ bool result; /* Présence à retourner */
+ size_t index; /* Indice du point d'insertion */
+
+ result = bsearch_index(label, kenum->cases_l2v, kenum->cases_l2v_count, sizeof(enum_value_t *),
+ (__compar_fn_t)compare_enum_values_by_sized_label, &index);
+
+ if (result)
+ *value = kenum->cases_l2v[index]->value;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = groupe d'énumérations à consulter. *
+* value = valeur concrète à transformer. *
+* prefix = détermine l'ajout d'un préfixe éventuel. *
+* *
+* Description : Traduit une constante d'énumération en étiquette brute. *
+* *
+* Retour : Désignation ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_kaitai_enum_find_label(const GKaitaiEnum *kenum, const resolved_value_t *value, bool prefix)
+{
+ char *result; /* Etiquette à retourner */
+ enum_value_t faked; /* Copie d'élément recherché */
+ bool found; /* Présence de partage existant*/
+ size_t index; /* Indice du point d'insertion */
+ const enum_value_t *item; /* Elément retrouvé par valeur */
+
+ faked.value = *value;
+
+ found = bsearch_index(&faked, kenum->cases_v2l, kenum->cases_v2l_count, sizeof(enum_value_t *),
+ (__compar_fn_t)compare_enum_values_by_value, &index);
+
+ if (found)
+ item = kenum->cases_l2v[index];
+ else
+ item = kenum->defcase;
+
+ if (item != NULL)
+ {
+ if (prefix)
+ asprintf(&result, "%s::%s", kenum->name, item->label);
+ else
+ result = strdup(item->label);
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kenum = groupe d'énumérations à consulter. *
+* value = valeur concrète à transformer. *
+* *
+* Description : Traduit une constante d'énumération en documentation. *
+* *
+* Retour : Documentation associée à la valeur indiquée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_kaitai_enum_find_documentation(const GKaitaiEnum *kenum, const resolved_value_t *value)
+{
+ char *result; /* Documentation à retourner */
+ enum_value_t faked; /* Copie d'élément recherché */
+ bool found; /* Présence de partage existant*/
+ size_t index; /* Indice du point d'insertion */
+ const enum_value_t *item; /* Elément retrouvé par valeur */
+
+ faked.value = *value;
+
+ found = bsearch_index(&faked, kenum->cases_v2l, kenum->cases_v2l_count, sizeof(enum_value_t *),
+ (__compar_fn_t)compare_enum_values_by_value, &index);
+
+ if (found)
+ item = kenum->cases_l2v[index];
+ else
+ item = kenum->defcase;
+
+ if (item != NULL)
+ result = strdup(item->doc);
+ else
+ result = NULL;
+
+ return result;
+
+}
diff --git a/plugins/kaitai/parsers/enum.h b/plugins/kaitai/parsers/enum.h
new file mode 100644
index 0000000..9e4bf2a
--- /dev/null
+++ b/plugins/kaitai/parsers/enum.h
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - prototypes pour la gestion des énumérations Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PARSERS_ENUM_H
+#define _PLUGINS_KAITAI_PARSERS_ENUM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#include <common/szstr.h>
+#include <plugins/yaml/node.h>
+
+
+#include "../expression.h"
+
+
+
+#define G_TYPE_KAITAI_ENUM g_kaitai_enum_get_type()
+#define G_KAITAI_ENUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_ENUM, GKaitaiEnum))
+#define G_IS_KAITAI_ENUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_ENUM))
+#define G_KAITAI_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_ENUM, GKaitaiEnumClass))
+#define G_IS_KAITAI_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_ENUM))
+#define G_KAITAI_ENUM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_ENUM, GKaitaiEnumClass))
+
+
+/* Définition d'un ensemble d'énumérations Kaitai (instance) */
+typedef struct _GKaitaiEnum GKaitaiEnum;
+
+/* Définition d'un ensemble d'énumérations Kaitai (classe) */
+typedef struct _GKaitaiEnumClass GKaitaiEnumClass;
+
+
+/* Indique le type défini pour un ensemble d'énumérations Kaitai. */
+GType g_kaitai_enum_get_type(void);
+
+/* Construit un groupe d'énumérations Kaitai. */
+GKaitaiEnum *g_kaitai_enum_new(GYamlNode *);
+
+/* Fournit le nom principal d'une énumération. */
+const char *g_kaitai_enum_get_name(const GKaitaiEnum *);
+
+/* Traduit une étiquette brute en constante d'énumération. */
+bool g_kaitai_enum_find_value(const GKaitaiEnum *, const sized_string_t *, resolved_value_t *);
+
+/* Traduit une constante d'énumération en étiquette brute. */
+char *g_kaitai_enum_find_label(const GKaitaiEnum *, const resolved_value_t *, bool);
+
+/* Traduit une constante d'énumération en documentation. */
+char *g_kaitai_enum_find_documentation(const GKaitaiEnum *, const resolved_value_t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_ENUM_H */
diff --git a/plugins/kaitai/parsers/instance-int.h b/plugins/kaitai/parsers/instance-int.h
new file mode 100644
index 0000000..6f098b4
--- /dev/null
+++ b/plugins/kaitai/parsers/instance-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance-int.h - prototypes pour les spécifications internes d'une instance Kaitai
+ *
+ * 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_PARSERS_INSTANCE_INT_H
+#define _PLUGINS_KAITAI_PARSERS_INSTANCE_INT_H
+
+
+#include "attribute-int.h"
+#include "instance.h"
+
+
+
+/* Spécification d'une instance Kaitai (instance) */
+struct _GKaitaiInstance
+{
+ GKaitaiAttribute parent; /* A laisser en premier */
+
+ char *name; /* Nom attribué à l'instance */
+
+ char *io; /* Contenu binaire forcé */
+ char *pos; /* Position forcée */
+ char *value; /* Formule pour calcul */
+
+};
+
+/* Spécification d'une instance Kaitai (classe) */
+struct _GKaitaiInstanceClass
+{
+ GKaitaiAttributeClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un lecteur d'instance Kaitai. */
+bool g_kaitai_instance_create(GKaitaiInstance *, GYamlNode *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_INSTANCE_INT_H */
diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c
new file mode 100644
index 0000000..d62c1f6
--- /dev/null
+++ b/plugins/kaitai/parsers/instance.c
@@ -0,0 +1,503 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.c - spécification d'une instance Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "instance.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <plugins/yaml/pair.h>
+
+
+#include "instance-int.h"
+#include "../expression.h"
+#include "../records/delayed.h"
+
+
+
+/* -------------------- CORRESPONDANCE ENTRE INSTANCE ET BINAIRE -------------------- */
+
+
+/* Initialise la classe des instances de spécification Kaitai. */
+static void g_kaitai_instance_class_init(GKaitaiInstanceClass *);
+
+/* Initialise une instance de spécification Kaitai. */
+static void g_kaitai_instance_init(GKaitaiInstance *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_instance_dispose(GKaitaiInstance *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_instance_finalize(GKaitaiInstance *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CORRESPONDANCE ENTRE INSTANCE ET BINAIRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une instance de la spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiInstance, g_kaitai_instance, G_TYPE_KAITAI_ATTRIBUTE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des instances de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_instance_class_init(GKaitaiInstanceClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GKaitaiParserClass *parser; /* Ancêtre parent de la classe */
+ GKaitaiAttributeClass *attrib; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_instance_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_instance_finalize;
+
+ parser = G_KAITAI_PARSER_CLASS(klass);
+
+ parser->parse = (parse_kaitai_fc)g_kaitai_instance_parse_content;
+
+ attrib = G_KAITAI_ATTRIBUTE_CLASS(klass);
+
+ attrib->get_label = (get_attribute_label_fc)g_kaitai_instance_get_name;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = instance à initialiser. *
+* *
+* Description : Initialise une instance de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_instance_init(GKaitaiInstance *inst)
+{
+ inst->name = NULL;
+
+ inst->io = NULL;
+ inst->pos = NULL;
+ inst->value = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_instance_dispose(GKaitaiInstance *inst)
+{
+ G_OBJECT_CLASS(g_kaitai_instance_parent_class)->dispose(G_OBJECT(inst));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_instance_finalize(GKaitaiInstance *inst)
+{
+ if (inst->name != NULL)
+ free(inst->name);
+
+ if (inst->io != NULL)
+ free(inst->io);
+
+ if (inst->pos != NULL)
+ free(inst->pos);
+
+ if (inst->value != NULL)
+ free(inst->value);
+
+ G_OBJECT_CLASS(g_kaitai_instance_parent_class)->finalize(G_OBJECT(inst));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = noeud Yaml contenant l'instance à constituer. *
+* *
+* Description : Construit un lecteur d'instance Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiInstance *g_kaitai_instance_new(GYamlNode *parent)
+{
+ GKaitaiInstance *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_INSTANCE, NULL);
+
+ if (!g_kaitai_instance_create(result, parent))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = lecteur d'instance Kaitai à initialiser pleinement. *
+* parent = noeud Yaml contenant l'instance à constituer. *
+* *
+* Description : Met en place un lecteur d'instance Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_instance_create(GKaitaiInstance *inst, GYamlNode *parent)
+{
+ bool result; /* Bilan à retourner */
+ const char *name; /* Désignation du type */
+ char *sub_path; /* Chemin d'accès suivant */
+ GYamlNode *sub; /* Contenu Yaml d'un type */
+ GYamlNode *node; /* Noeud particulier présent */
+ const char *value; /* Valeur Yaml particulière */
+
+ result = false;
+
+ /* Extraction du nom */
+
+ if (!G_IS_YAML_PAIR(parent))
+ goto exit;
+
+ name = g_yaml_pair_get_key(G_YAML_PAIR(parent));
+
+ inst->name = strdup(name);
+
+ /* Extraction des bases du type */
+
+ asprintf(&sub_path, "/%s/", name);
+ sub = g_yaml_node_find_first_by_path(parent, sub_path);
+ free(sub_path);
+
+ if (sub == NULL)
+ goto exit;
+
+ result = g_kaitai_attribute_create(G_KAITAI_ATTRIBUTE(inst), sub, false);
+
+ /* Eventuel contenu imposé */
+
+ node = g_yaml_node_find_first_by_path(sub, "/io");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+ if (value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_loading;
+ }
+
+ inst->io = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Eventuelle positiion imposée */
+
+ node = g_yaml_node_find_first_by_path(sub, "/pos");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+ if (value == NULL)
+ {
+ g_object_unref(G_OBJECT(node));
+ goto bad_loading;
+ }
+
+ inst->pos = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
+
+ }
+
+ /* Eventuelle formule de calcul d'une valeur */
+
+ node = g_yaml_node_find_first_by_path(sub, "/value");
+
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
+
+ inst->value = g_yaml_pair_aggregate_value(G_YAML_PAIR(node));
+
+ g_object_unref(G_OBJECT(node));
+
+ if (inst->value == NULL)
+ goto bad_loading;
+
+ }
+
+ bad_loading:
+
+ g_object_unref(G_OBJECT(sub));
+
+ exit:
+
+ if (result)
+ result = (inst->pos != NULL || inst->value != NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = lecteur d'instance Kaitai à consulter. *
+* *
+* Description : Indique le nom attribué à une instance Kaitai. *
+* *
+* Retour : Désignation pointant l'instance. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst)
+{
+ char *result; /* Valeur à renvoyer */
+
+ result = inst->name;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = lecteur d'instance Kaitai à consulter. *
+* locals = variables locales pour les résolutions de types. *
+* content = contenu binaire lié à la correspondance. *
+* *
+* Description : Détermine la valeur effective d'un élément Kaitai dynamique. *
+* *
+* Retour : valeur à sauvegarder sous une forme générique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
+{
+ GMatchRecord *result; /* Enregistrement à retourner */
+ GBinContent *work_area; /* Aire de travail */
+ GKaitaiStream *stream; /* Flux de données pour Kaitai */
+ 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 */
+
+ result = NULL;
+
+ if (inst->value == NULL)
+ {
+ /* Contenu particulier */
+
+ if (inst->io == NULL)
+ work_area = content;
+
+ else
+ {
+ 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);
+
+ g_object_unref(G_OBJECT(stream));
+
+ }
+
+ /* Tête de lecture */
+
+ g_binary_content_compute_start_pos(work_area, &forced_pos);
+
+ 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);
+
+ else
+ {
+ assert(offset.type == GVT_SIGNED_INTEGER);
+
+ if (offset.signed_integer < 0)
+ {
+ status = false;
+ goto exit_with_content;
+ }
+
+ advance_vmpa(&forced_pos, offset.signed_integer);
+
+ }
+
+ /* Lecture */
+
+ class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class);
+
+ init_evmpa_from_vmpa(&epos, &forced_pos);
+
+ class->parse(G_KAITAI_PARSER(inst), locals, work_area, &epos, &result);
+
+ exit_with_content:
+
+ if (work_area != content)
+ g_object_unref(G_OBJECT(work_area));
+
+ }
+
+ exit:
+
+ 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
new file mode 100644
index 0000000..4594137
--- /dev/null
+++ b/plugins/kaitai/parsers/instance.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.h - prototypes pour la spécification d'une instance Kaitai
+ *
+ * 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_PARSERS_INSTANCE_H
+#define _PLUGINS_KAITAI_PARSERS_INSTANCE_H
+
+
+#include <glib-object.h>
+
+
+#include <plugins/yaml/node.h>
+
+
+#include "../expression.h"
+#include "../scope.h"
+
+
+
+#define G_TYPE_KAITAI_INSTANCE g_kaitai_instance_get_type()
+#define G_KAITAI_INSTANCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_INSTANCE, GKaitaiInstance))
+#define G_IS_KAITAI_INSTANCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_INSTANCE))
+#define G_KAITAI_INSTANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_INSTANCE, GKaitaiInstanceClass))
+#define G_IS_KAITAI_INSTANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_INSTANCE))
+#define G_KAITAI_INSTANCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_INSTANCE, GKaitaiInstanceClass))
+
+
+/* Spécification d'une instance Kaitai (instance) */
+typedef struct _GKaitaiInstance GKaitaiInstance;
+
+/* Spécification d'une instance Kaitai (classe) */
+typedef struct _GKaitaiInstanceClass GKaitaiInstanceClass;
+
+
+/* Indique le type défini pour une instance de la spécification Kaitai. */
+GType g_kaitai_instance_get_type(void);
+
+/* Construit un lecteur d'instance Kaitai. */
+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 *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_INSTANCE_H */
diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h
new file mode 100644
index 0000000..5fe9174
--- /dev/null
+++ b/plugins/kaitai/parsers/meta-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta-int.h - prototypes internes pour la description globale d'une définition Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_PARSERS_META_INT_H
+#define PLUGINS_KAITAI_PARSERS_META_INT_H
+
+
+#include "meta.h"
+
+
+
+/* Description globale d'une définition Kaitai (instance) */
+struct _GKaitaiMeta
+{
+ GObject parent; /* A laisser en premier */
+
+ char *id; /* Identifiant attribué */
+ char *title; /* Désignation de la définition*/
+
+ 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) */
+struct _GKaitaiMetaClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une description globale Kaitai. */
+bool g_kaitai_meta_create(GKaitaiMeta *, GYamlNode *);
+
+
+
+#endif /* PLUGINS_KAITAI_PARSERS_META_INT_H */
diff --git a/plugins/yaml/line.c b/plugins/kaitai/parsers/meta.c
index 26a1012..132eefd 100644
--- a/plugins/yaml/line.c
+++ b/plugins/kaitai/parsers/meta.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * line.c - ligne de contenu Yaml
+ * meta.c - description globale d'une définition Kaitai
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,66 +21,44 @@
*/
-#include "line.h"
+#include "meta.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
-#include <core/logs.h>
+#include <plugins/yaml/pair.h>
+#include "meta-int.h"
-/* Ligne de données au format Yaml (instance) */
-struct _GYamlLine
-{
- GObject parent; /* A laisser en premier */
-
- char *raw; /* Contenu brut de la ligne */
- size_t number; /* Indice associé */
-
- size_t indent; /* Niveau d'indentation */
- bool is_list_item; /* Elément de liste ? */
-
- const char *payload; /* Charge utile du contenu */
-
- char *key; /* Clef de la ligne Yaml */
- char *value; /* Valeyr de la ligne Yaml */
-
-};
-
-/* Ligne de données au format Yaml (classe) */
-struct _GYamlLineClass
-{
- GObjectClass parent; /* A laisser en premier */
-};
+/* Initialise la classe des descriptions globales Kaitai. */
+static void g_kaitai_meta_class_init(GKaitaiMetaClass *);
-/* Initialise la classe des lignes de contenu Yaml. */
-static void g_yaml_line_class_init(GYamlLineClass *);
-
-/* Initialise une instance de ligne de contenu Yaml. */
-static void g_yaml_line_init(GYamlLine *);
+/* Initialise une description globale de définition Kaitai. */
+static void g_kaitai_meta_init(GKaitaiMeta *);
/* Supprime toutes les références externes. */
-static void g_yaml_line_dispose(GYamlLine *);
+static void g_kaitai_meta_dispose(GKaitaiMeta *);
/* Procède à la libération totale de la mémoire. */
-static void g_yaml_line_finalize(GYamlLine *);
+static void g_kaitai_meta_finalize(GKaitaiMeta *);
-/* Indique le type défini pour une ligne de données au format Yaml. */
-G_DEFINE_TYPE(GYamlLine, g_yaml_line, G_TYPE_OBJECT);
+/* Indique le type défini pour une description globale Kaitai. */
+G_DEFINE_TYPE(GKaitaiMeta, g_kaitai_meta, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des lignes de contenu Yaml. *
+* Description : Initialise la classe des descriptions globales Kaitai. *
* *
* Retour : - *
* *
@@ -88,23 +66,23 @@ G_DEFINE_TYPE(GYamlLine, g_yaml_line, G_TYPE_OBJECT);
* *
******************************************************************************/
-static void g_yaml_line_class_init(GYamlLineClass *klass)
+static void g_kaitai_meta_class_init(GKaitaiMetaClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_yaml_line_dispose;
- object->finalize = (GObjectFinalizeFunc)g_yaml_line_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_meta_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_meta_finalize;
}
/******************************************************************************
* *
-* Paramètres : line = instance à initialiser. *
+* Paramètres : meta = instance à initialiser. *
* *
-* Description : Initialise une instance de ligne de contenu Yaml. *
+* Description : Initialise une description globale de définition Kaitai. *
* *
* Retour : - *
* *
@@ -112,24 +90,22 @@ static void g_yaml_line_class_init(GYamlLineClass *klass)
* *
******************************************************************************/
-static void g_yaml_line_init(GYamlLine *line)
+static void g_kaitai_meta_init(GKaitaiMeta *meta)
{
- line->raw = NULL;
- line->number = -1;
+ meta->id = NULL;
+ meta->title = NULL;
- line->indent = 0;
- line->is_list_item = false;
+ meta->endian = SRE_LITTLE;
- line->payload = NULL;
- line->key = NULL;
- line->value = NULL;
+ meta->dependencies = NULL;
+ meta->dep_count = 0;
}
/******************************************************************************
* *
-* Paramètres : line = instance d'objet GLib à traiter. *
+* Paramètres : meta = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -139,16 +115,16 @@ static void g_yaml_line_init(GYamlLine *line)
* *
******************************************************************************/
-static void g_yaml_line_dispose(GYamlLine *line)
+static void g_kaitai_meta_dispose(GKaitaiMeta *meta)
{
- G_OBJECT_CLASS(g_yaml_line_parent_class)->dispose(G_OBJECT(line));
+ G_OBJECT_CLASS(g_kaitai_meta_parent_class)->dispose(G_OBJECT(meta));
}
/******************************************************************************
* *
-* Paramètres : line = instance d'objet GLib à traiter. *
+* Paramètres : meta = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -158,28 +134,32 @@ static void g_yaml_line_dispose(GYamlLine *line)
* *
******************************************************************************/
-static void g_yaml_line_finalize(GYamlLine *line)
+static void g_kaitai_meta_finalize(GKaitaiMeta *meta)
{
- if (line->raw != NULL)
- free(line->raw);
+ size_t i; /* Boucle de parcours */
+
+ if (meta->id != NULL)
+ free(meta->id);
- if (line->key != NULL)
- free(line->key);
+ if (meta->title != NULL)
+ free(meta->title);
- if (line->value != NULL)
- free(line->value);
+ for (i = 0; i < meta->dep_count; i++)
+ free(meta->dependencies[i]);
- G_OBJECT_CLASS(g_yaml_line_parent_class)->finalize(G_OBJECT(line));
+ if (meta->dependencies != NULL)
+ free(meta->dependencies);
+
+ G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta));
}
/******************************************************************************
* *
-* Paramètres : raw = contenu brut d'une ligne au format Yaml. *
-* number = indice associé à la ligne. *
+* Paramètres : parent = noeud Yaml contenant l'attribut à constituer. *
* *
-* Description : Met en place un gestionnaire pour ligne au format Yaml. *
+* Description : Construit une description globale Kaitai. *
* *
* Retour : Instance mise en place ou NULL en cas d'échec. *
* *
@@ -187,120 +167,136 @@ static void g_yaml_line_finalize(GYamlLine *line)
* *
******************************************************************************/
-GYamlLine *g_yaml_line_new(const char *raw, size_t number)
+GKaitaiMeta *g_kaitai_meta_new(GYamlNode *parent)
{
- GYamlLine *result; /* Structure à retourner */
- char *iter; /* Boucle de parcours */
- bool string_content[2]; /* Ouvertures de chaînes */
- bool escape; /* Echappement de marquant */
+ GKaitaiMeta *result; /* Identifiant à retourner */
- result = g_object_new(G_TYPE_YAML_LINE, NULL);
+ result = g_object_new(G_TYPE_KAITAI_META, NULL);
- result->raw = strdup(raw);
- result->number = number;
+ if (!g_kaitai_meta_create(result, parent))
+ g_clear_object(&result);
- /* Indentation */
+ return result;
- for (iter = result->raw; *iter != '\0'; iter++)
- {
- if (*iter != ' ')
- break;
+}
- result->indent++;
- }
+/******************************************************************************
+* *
+* Paramètres : meta = description globale à initialiser pleinement. *
+* parent = noeud Yaml contenant l'attribut à constituer. *
+* *
+* Description : Met en place une description globale Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- if (*iter == '-')
+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;
+
+ /* Identifiant */
+
+ node = g_yaml_node_find_first_by_path(parent, "/meta/id");
+
+ if (node != NULL)
{
- result->is_list_item = true;
+ assert(G_IS_YAML_PAIR(node));
- for (iter++; *iter != '\0'; iter++)
- if (*iter != ' ')
- break;
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
- }
+ if (value != NULL)
+ meta->id = strdup(value);
+
+ g_object_unref(G_OBJECT(node));
- result->payload = iter;
+ }
- /* Eventuel couple clef/valeur */
+ /* Titre */
- string_content[0] = false;
- string_content[1] = false;
+ node = g_yaml_node_find_first_by_path(parent, "/meta/title");
- for (; *iter != '\0'; iter++)
+ if (node != NULL)
{
- if (*iter == '\'' && !string_content[1])
- {
- if (iter == result->payload)
- escape = false;
+ assert(G_IS_YAML_PAIR(node));
- else
- escape = *(iter - 1) == '\'';
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
- if (!escape)
- string_content[0] = !string_content[0];
+ if (value != NULL)
+ meta->title = strdup(value);
- }
+ g_object_unref(G_OBJECT(node));
- else if (*iter == '"' && !string_content[0])
- {
- if (iter == result->payload)
- escape = false;
+ }
- else
- escape = *(iter - 1) == '\\';
+ /* Boutisme */
- if (!escape)
- string_content[1] = !string_content[1];
+ node = g_yaml_node_find_first_by_path(parent, "/meta/endian");
- }
+ if (node != NULL)
+ {
+ assert(G_IS_YAML_PAIR(node));
- else if (!string_content[0] && !string_content[1])
- {
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
- if (*iter == ':')
- break;
+ if (strcmp(value, "le") == 0)
+ meta->endian = SRE_LITTLE;
+ else if (strcmp(value, "be") == 0)
+ meta->endian = SRE_BIG;
- }
+ g_object_unref(G_OBJECT(node));
}
- if (*iter != '\0')
+ /* Imports */
+
+ node = g_yaml_node_find_first_by_path(parent, "/meta/imports/");
+
+ if (node != NULL)
{
- result->key = strndup(result->payload, iter - result->payload);
+ result = G_IS_YAML_COLLEC(node);
- for (iter++; *iter != '\0'; iter++)
- if (*iter != ' ')
- break;
+ if (result)
+ {
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(node), &count);
- if (*iter != '\0')
- result->value = strdup(iter);
+ 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]));
- return result;
+ 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]));
-/******************************************************************************
-* *
-* Paramètres : line = ligne au format Yaml à consulter. *
-* *
-* Description : Fournit la taille de l'indentation d'une ligne Yaml. *
-* *
-* Retour : Taille de l'indentation rencontrée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ }
-size_t g_yaml_line_count_indent(const GYamlLine *line)
-{
- size_t result; /* Quantité à retourner */
+ result = (i == count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
- result = line->indent;
+ if (nodes != NULL)
+ free(nodes);
+
+ }
+
+ }
return result;
@@ -309,21 +305,21 @@ size_t g_yaml_line_count_indent(const GYamlLine *line)
/******************************************************************************
* *
-* Paramètres : line = ligne au format Yaml à consulter. *
+* Paramètres : meta = description globale à consulter. *
* *
-* Description : Indique si la ligne représente un élément de liste. *
+* Description : Fournit l'identifié associé à une définiton Kaitai. *
* *
-* Retour : Statut de l'état lié à une liste d'éléments. *
+* Retour : Identifiant de définition complète ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_yaml_line_is_list_item(const GYamlLine *line)
+const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta)
{
- bool result; /* Statut à retourner */
+ const char *result; /* Chaîne à retourner */
- result = line->is_list_item;
+ result = meta->id;
return result;
@@ -332,21 +328,21 @@ bool g_yaml_line_is_list_item(const GYamlLine *line)
/******************************************************************************
* *
-* Paramètres : line = ligne au format Yaml à consulter. *
+* Paramètres : meta = description globale à consulter. *
* *
-* Description : Fournit la charge utile associée à une ligne Yaml. *
+* Description : Fournit la désignation humaine d'une définiton Kaitai. *
* *
-* Retour : Contenu sous forme de chaîne de caractères. *
+* Retour : Intitulé de définition ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_yaml_line_get_payload(const GYamlLine *line)
+const char *g_kaitai_meta_get_title(const GKaitaiMeta *meta)
{
- const char *result; /* Valeur à retourner */
+ const char *result; /* Chaîne à retourner */
- result = line->payload;
+ result = meta->title;
return result;
@@ -355,21 +351,21 @@ const char *g_yaml_line_get_payload(const GYamlLine *line)
/******************************************************************************
* *
-* Paramètres : line = ligne au format Yaml à consulter. *
+* Paramètres : meta = description globale à consulter. *
* *
-* Description : Fournit la clef associée à une ligne Yaml si elle existe. *
+* Description : Indique le boustime observé par défaut par une définiton. *
* *
-* Retour : Clef sous forme de chaîne de caractères ou NULL. *
+* Retour : Boustime, petit par défaut. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_yaml_line_get_key(const GYamlLine *line)
+SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta)
{
- char *result; /* Valeur à retourner */
+ SourceEndian result; /* Chaîne à retourner */
- result = line->key;
+ result = meta->endian;
return result;
@@ -378,21 +374,24 @@ const char *g_yaml_line_get_key(const GYamlLine *line)
/******************************************************************************
* *
-* Paramètres : line = ligne au format Yaml à consulter. *
+* Paramètres : meta = description globale à consulter. *
+* count = quantité de définitions à importer. [OUT] *
* *
-* Description : Fournit la valeur associée à une ligne Yaml si elle existe. *
+* Description : Indique la liste des définitions à importer. *
* *
-* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* Retour : Liste de désignations de définitions ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_yaml_line_get_value(const GYamlLine *line)
+const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *meta, size_t *count)
{
- char *result; /* Valeur à retourner */
+ const char * const *result; /* Liste à retourner */
+
+ result = (const char * const *)meta->dependencies;
- result = line->value;
+ *count = meta->dep_count;
return result;
diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h
new file mode 100644
index 0000000..b8b685d
--- /dev/null
+++ b/plugins/kaitai/parsers/meta.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta.h - prototypes pour la description globale d'une définition Kaitai
+ *
+ * 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_PARSERS_META_H
+#define _PLUGINS_KAITAI_PARSERS_META_H
+
+
+#include <glib-object.h>
+
+
+#include <common/endianness.h>
+#include <plugins/yaml/node.h>
+
+
+
+#define G_TYPE_KAITAI_META g_kaitai_meta_get_type()
+#define G_KAITAI_META(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_META, GKaitaiMeta))
+#define G_IS_KAITAI_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_META))
+#define G_KAITAI_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_META, GKaitaiMetaClass))
+#define G_IS_KAITAI_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_META))
+#define G_KAITAI_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_META, GKaitaiMetaClass))
+
+
+/* Description globale d'une définition Kaitai (instance) */
+typedef struct _GKaitaiMeta GKaitaiMeta;
+
+/* Description globale d'une définition Kaitai (classe) */
+typedef struct _GKaitaiMetaClass GKaitaiMetaClass;
+
+
+/* Indique le type défini pour une description globale Kaitai. */
+GType g_kaitai_meta_get_type(void);
+
+/* Construit une description globale Kaitai. */
+GKaitaiMeta *g_kaitai_meta_new(GYamlNode *);
+
+/* Fournit l'identifié associé à une définiton Kaitai. */
+const char *g_kaitai_meta_get_id(const GKaitaiMeta *);
+
+/* Fournit la désignation humaine d'une définiton Kaitai. */
+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
new file mode 100644
index 0000000..6eb6e53
--- /dev/null
+++ b/plugins/kaitai/parsers/struct-int.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct-int.h - prototypes internes pour la définition d'une structure Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_PARSERS_STRUCT_INT_H
+#define PLUGINS_KAITAI_PARSERS_STRUCT_INT_H
+
+
+#include "attribute.h"
+#include "instance.h"
+#include "struct.h"
+#include "../parser-int.h"
+
+
+
+/* Spécification d'une structure Kaitai (instance) */
+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 */
+ size_t seq_items_count; /* Quantité de ces attributs */
+
+ GKaitaiType **types; /* Types particuliers définis */
+ size_t types_count; /* Quantité de ces types */
+
+ GKaitaiInstance **instances; /* Instances prises en charge */
+ size_t instances_count; /* Quantité de ces instances */
+
+ GKaitaiEnum **enums; /* Enumérations locales */
+ size_t enums_count; /* Quantité de ces énumérations*/
+
+};
+
+/* Spécification d'une structure Kaitai (classe) */
+struct _GKaitaiStructClass
+{
+ GKaitaiParserClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un interpréteur de définitions Kaitai. */
+bool g_kaitai_structure_create_from_text(GKaitaiStruct *, const char *);
+
+/* Met en place un interpréteur de définitions Kaitai. */
+bool g_kaitai_structure_create_from_file(GKaitaiStruct *, const char *);
+
+/* Met en place un lecteur de définitions Kaitai. */
+bool g_kaitai_structure_create(GKaitaiStruct *, GYamlNode *);
+
+
+
+#endif /* PLUGINS_KAITAI_PARSERS_STRUCT_INT_H */
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
new file mode 100644
index 0000000..d447cf3
--- /dev/null
+++ b/plugins/kaitai/parsers/struct.c
@@ -0,0 +1,837 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.c - définition d'une structure Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "struct.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <plugins/yaml/collection.h>
+#include <plugins/yaml/parser.h>
+
+
+#include "struct-int.h"
+#include "../import.h"
+#include "../parser.h"
+#include "../records/empty.h"
+#include "../records/group.h"
+
+
+
+/* ---------------------- LECTURE D'UNE TRANCHE DE DEFINITIONS ---------------------- */
+
+
+/* Initialise la classe des structuts de spécification Kaitai. */
+static void g_kaitai_structure_class_init(GKaitaiStructClass *);
+
+/* Initialise un structut de spécification Kaitai. */
+static void g_kaitai_structure_init(GKaitaiStruct *);
+
+/* Supprime toutes les références externes. */
+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 *, ext_vmpa_t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* LECTURE D'UNE TRANCHE DE DEFINITIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un structut de la spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiStruct, g_kaitai_structure, G_TYPE_KAITAI_PARSER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des structuts de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_structure_class_init(GKaitaiStructClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GKaitaiParserClass *parser; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_structure_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_structure_finalize;
+
+ parser = G_KAITAI_PARSER_CLASS(klass);
+
+ parser->parse = (parse_kaitai_fc)g_kaitai_structure_parse_content;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = instance à initialiser. *
+* *
+* Description : Initialise un structure de spécification Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_structure_init(GKaitaiStruct *kstruct)
+{
+ kstruct->filename = NULL;
+
+ kstruct->meta = NULL;
+
+ kstruct->seq_items = NULL;
+ kstruct->seq_items_count = 0;
+
+ kstruct->types = NULL;
+ kstruct->types_count = 0;
+
+ kstruct->instances = NULL;
+ kstruct->instances_count = 0;
+
+ kstruct->enums = NULL;
+ kstruct->enums_count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_clear_object(&kstruct->meta);
+
+ for (i = 0; i < kstruct->seq_items_count; i++)
+ g_clear_object(&kstruct->seq_items[i]);
+
+ for (i = 0; i < kstruct->types_count; i++)
+ g_clear_object(&kstruct->types[i]);
+
+ for (i = 0; i < kstruct->instances_count; i++)
+ g_clear_object(&kstruct->instances[i]);
+
+ for (i = 0; i < kstruct->enums_count; i++)
+ g_clear_object(&kstruct->enums[i]);
+
+ G_OBJECT_CLASS(g_kaitai_structure_parent_class)->dispose(G_OBJECT(kstruct));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct)
+{
+ if (kstruct->filename != NULL)
+ free(kstruct->filename);
+
+ if (kstruct->seq_items != NULL)
+ free(kstruct->seq_items);
+
+ if (kstruct->types != NULL)
+ free(kstruct->types);
+
+ if (kstruct->instances != NULL)
+ free(kstruct->instances);
+
+ if (kstruct->enums != NULL)
+ free(kstruct->enums);
+
+ G_OBJECT_CLASS(g_kaitai_structure_parent_class)->finalize(G_OBJECT(kstruct));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : text = définitions textuelles d'un contenu brut. *
+* *
+* Description : Crée un nouvel interpréteur de structure Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiStruct *g_kaitai_structure_new_from_text(const char *text)
+{
+ GKaitaiStruct *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_STRUCT, NULL);
+
+ if (!g_kaitai_structure_create_from_text(result, text))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = lecteur de définition à initialiser pleinement. *
+* text = définitions textuelles d'un contenu brut. *
+* *
+* Description : Met en place un interpréteur de définitions Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_structure_create_from_text(GKaitaiStruct *kstruct, const char *text)
+{
+ bool result; /* Bilan à retourner */
+ GYamlNode *root; /* Noeud racine YAML */
+
+ root = parse_yaml_from_text(text, strlen(text));
+
+ if (root != NULL)
+ {
+ result = g_kaitai_structure_create(kstruct, root);
+ g_object_unref(G_OBJECT(root));
+ }
+ else
+ {
+ fprintf(stderr, "The provided YAML content seems invalid");
+ result = false;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = chemin vers des définitions de règles. *
+* *
+* Description : Crée un nouvel interpréteur de structure Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiStruct *g_kaitai_structure_new_from_file(const char *filename)
+{
+ GKaitaiStruct *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_STRUCT, NULL);
+
+ if (!g_kaitai_structure_create_from_file(result, filename))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = lecteur de définition à initialiser pleinement. *
+* filename = chemin vers des définitions de règles. *
+* *
+* Description : Met en place un interpréteur de définitions Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *filename)
+{
+ bool result; /* Bilan à retourner */
+ GYamlNode *root; /* Noeud racine YAML */
+
+ kstruct->filename = strdup(filename);
+
+ root = parse_yaml_from_file(filename);
+
+ if (root != NULL)
+ {
+ result = g_kaitai_structure_create(kstruct, root);
+ g_object_unref(G_OBJECT(root));
+ }
+ else
+ {
+ fprintf(stderr, "The provided YAML content seems invalid");
+ result = false;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = lecteur de définition à initialiser pleinement. *
+* parent = noeud Yaml contenant l'attribut à constituer. *
+* *
+* Description : Met en place un lecteur de définitions Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
+{
+ bool result; /* Bilan à retourner */
+ GYamlNode *collec; /* Liste de noeuds à traiter */
+ 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;
+
+ /* Informations générales */
+
+ 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/");
+
+ if (collec != NULL)
+ {
+ if (G_IS_YAML_COLLEC(collec))
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+ else
+ count = 0;
+
+ if (count > 0)
+ {
+ kstruct->seq_items = calloc(count, sizeof(GKaitaiAttribute *));
+ kstruct->seq_items_count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ kstruct->seq_items[i] = g_kaitai_attribute_new(nodes[i]);
+ if (kstruct->seq_items[i] == NULL) break;
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
+
+ failed = (i < count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ free(nodes);
+
+ if (failed)
+ goto bad_loading;
+
+ }
+
+ g_object_unref(G_OBJECT(collec));
+
+ }
+
+ /* Types particuliers éventuels */
+
+ collec = g_yaml_node_find_first_by_path(parent, "/types/");
+
+ if (collec != NULL)
+ {
+ if (G_IS_YAML_COLLEC(collec))
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+ else
+ count = 0;
+
+ if (count > 0)
+ {
+ 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[first + i] = g_kaitai_type_new(nodes[i]);
+ if (kstruct->types[first + i] == NULL) break;
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
+
+ failed = (i < count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ free(nodes);
+
+ if (failed)
+ goto bad_loading;
+
+ }
+
+ g_object_unref(G_OBJECT(collec));
+
+ }
+
+ /* Instances éventuelles */
+
+ collec = g_yaml_node_find_first_by_path(parent, "/instances/");
+
+ if (collec != NULL)
+ {
+ if (G_IS_YAML_COLLEC(collec))
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+ else
+ count = 0;
+
+ if (count > 0)
+ {
+ kstruct->instances = calloc(count, sizeof(GKaitaiInstance *));
+ kstruct->instances_count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ kstruct->instances[i] = g_kaitai_instance_new(nodes[i]);
+ if (kstruct->instances[i] == NULL) break;
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
+
+ failed = (i < count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ free(nodes);
+
+ if (failed)
+ goto bad_loading;
+
+ }
+
+ g_object_unref(G_OBJECT(collec));
+
+ }
+
+ /* Enumérations éventuelles */
+
+ collec = g_yaml_node_find_first_by_path(parent, "/enums/");
+
+ if (collec != NULL)
+ {
+ if (G_IS_YAML_COLLEC(collec))
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+ else
+ count = 0;
+
+ if (count > 0)
+ {
+ kstruct->enums = calloc(count, sizeof(GKaitaiEnum *));
+ kstruct->enums_count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ kstruct->enums[i] = g_kaitai_enum_new(nodes[i]);
+ if (kstruct->enums[i] == NULL) break;
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
+
+ failed = (i < count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ free(nodes);
+
+ if (failed)
+ goto bad_loading;
+
+ }
+
+ g_object_unref(G_OBJECT(collec));
+
+ }
+
+ /* Sortie heureuse */
+
+ result = true;
+
+ bad_loading:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Description de la définition Kaitai courante. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiMeta *g_kaitai_structure_get_meta(const GKaitaiStruct *kstruct)
+{
+ GKaitaiMeta *result; /* Informations à retourner */
+
+ result = kstruct->meta;
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = structure Kaitai en cours de parcours. *
+* name = désignation principale des énumérations ciblées. *
+* *
+* Description : Fournit un ensemble d'énumérations locales de la structure. *
+* *
+* Retour : Enumérations locales ou NULL si non trouvée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiEnum *g_kaitai_structure_get_enum(const GKaitaiStruct *kstruct, const sized_string_t *name)
+{
+ GKaitaiEnum *result; /* Instance à retourner */
+ size_t i; /* Boucle de parcours */
+ const char *other; /* Autre désignation à comparer*/
+
+ result = NULL;
+
+ for (i = 0; i < kstruct->enums_count; i++)
+ {
+ other = g_kaitai_enum_get_name(kstruct->enums[i]);
+
+ if (strncmp(name->data, other, name->len) == 0) // FIXME
+ {
+ result = kstruct->enums[i];
+ g_object_ref(G_OBJECT(result));
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = structure Kaitai en cours de parcours. *
+* name = désignation du type particulier ciblé. *
+* *
+* Description : Recherche la définition d'un type nouveau pour Kaitai. *
+* *
+* Retour : Type prêt à emploi ou NULL si non trouvé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, const char *name)
+{
+ GKaitaiType *result; /* Instance à retourner */
+ size_t i; /* Boucle de parcours */
+ const char *other; /* Autre désignation à comparer*/
+
+ result = NULL;
+
+ for (i = 0; i < kstruct->types_count; i++)
+ {
+ other = g_kaitai_type_get_name(kstruct->types[i]);
+
+ if (strcmp(name, other) == 0)
+ {
+ result = kstruct->types[i];
+ g_object_ref(G_OBJECT(result));
+ break;
+ }
+
+ result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(kstruct->types[i]), name);
+ if (result != NULL) break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = structure Kaitai en cours de parcours. *
+* content = contenu binaire en cours de traitement. *
+* *
+* Description : Parcourt un contenu binaire selon une description Kaitai. *
+* *
+* Retour : Arborescence d'éléments rencontrés selon les spécifications. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *content)
+{
+ GMatchRecord *result; /* Arborescence à retourner */
+ vmpa2t pos; /* Tête de lecture */
+ kaitai_scope_t locals; /* Variables locales */
+ ext_vmpa_t epos; /* Tête de lecture complète */
+
+ g_binary_content_compute_start_pos(content, &pos);
+
+ init_record_scope(&locals, kstruct->meta);
+
+ init_evmpa_from_vmpa(&epos, &pos);
+
+ g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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. *
+* 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_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 */
+ GMatchRecord *old; /* Sauvegarde de valeur */
+ size_t i; /* Boucle de parcours */
+ GMatchRecord *child; /* Nouvel élément mis en place */
+
+ result = true;
+
+ /* 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, &epos->base));
+
+ if (locals->root == NULL)
+ locals->root = *record;
+
+ }
+
+ /* Sinon on construit selon les définitions fournies */
+ else
+ {
+ group = g_record_group_new(kstruct, content);
+ *record = G_MATCH_RECORD(group);
+
+ if (locals->root == NULL)
+ locals->root = *record;
+
+ old = locals->parent;
+ locals->parent = *record;
+
+ /**
+ * 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->instances[i]),
+ locals, content, epos, &child);
+ if (!result) goto exit;
+
+ if (child != NULL)
+ {
+ g_record_group_add_record(group, child);
+ g_object_unref(G_OBJECT(child));
+ }
+
+ }
+
+ /**
+ * Seconde phase.
+ */
+
+ locals->parent = *record;
+
+ for (i = 0; i < kstruct->seq_items_count; i++)
+ {
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
+ locals, content, epos, &child);
+ if (!result) goto exit;
+
+ if (child != NULL)
+ {
+ g_record_group_add_record(group, child);
+ g_object_unref(G_OBJECT(child));
+ }
+
+ }
+
+ exit:
+
+ locals->parent = old;
+
+ if (!result)
+ g_clear_object(record);
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/parsers/struct.h b/plugins/kaitai/parsers/struct.h
new file mode 100644
index 0000000..4a2397a
--- /dev/null
+++ b/plugins/kaitai/parsers/struct.h
@@ -0,0 +1,80 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.h - prototypes pour la définition d'une structure Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PARSERS_STRUCT_H
+#define _PLUGINS_KAITAI_PARSERS_STRUCT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+
+
+#include "enum.h"
+#include "meta.h"
+#include "type.h"
+#include "../record.h"
+
+
+
+#define G_TYPE_KAITAI_STRUCT g_kaitai_structure_get_type()
+#define G_KAITAI_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_STRUCT, GKaitaiStruct))
+#define G_IS_KAITAI_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_STRUCT))
+#define G_KAITAI_STRUCT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_STRUCT, GKaitaiStructClass))
+#define G_IS_KAITAI_STRUCT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_STRUCT))
+#define G_KAITAI_STRUCT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_STRUCT, GKaitaiStructClass))
+
+
+/* Spécification d'une structure Kaitai (instance) */
+typedef struct _GKaitaiStruct GKaitaiStruct;
+
+/* Spécification d'une structure Kaitai (classe) */
+typedef struct _GKaitaiStructClass GKaitaiStructClass;
+
+
+/* Indique le type défini pour une structure Kaitai. */
+GType g_kaitai_structure_get_type(void);
+
+/* Crée un nouvel interpréteur de structure Kaitai. */
+GKaitaiStruct *g_kaitai_structure_new_from_text(const char *);
+
+/* Crée un nouvel interpréteur de structure Kaitai. */
+GKaitaiStruct *g_kaitai_structure_new_from_file(const char *);
+
+/* Fournit la description globale d'une définition Kaitai. */
+GKaitaiMeta *g_kaitai_structure_get_meta(const GKaitaiStruct *);
+
+/* Recherche la définition d'un type nouveau pour Kaitai. */
+GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *, const char *);
+
+/* Fournit un ensemble d'énumérations locales de la structure. */
+GKaitaiEnum *g_kaitai_structure_get_enum(const GKaitaiStruct *, const sized_string_t *);
+
+/* Parcourt un contenu binaire selon une description Kaitai. */
+GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *, GBinContent *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_STRUCT_H */
diff --git a/plugins/kaitai/parsers/switch-int.h b/plugins/kaitai/parsers/switch-int.h
new file mode 100644
index 0000000..a087e49
--- /dev/null
+++ b/plugins/kaitai/parsers/switch-int.h
@@ -0,0 +1,78 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * switch-int.h - prototypes internes pour la gestion des énumérations Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_PARSERS_SWITCH_INT_H
+#define PLUGINS_KAITAI_PARSERS_SWITCH_INT_H
+
+
+#include "switch.h"
+#include "../parser-int.h"
+
+
+
+/* ------------------------ BASCULE DYNAMIQUE SELON CONTEXTE ------------------------ */
+
+
+/* Mémorisation d'une valeur d'énumération */
+typedef struct _switch_case_t
+{
+ char *value; /* Valeur d'association */
+ char *type; /* Désignation du type associé */
+
+} switch_case_t;
+
+
+
+/* ----------------------- SELECTION DYNAMIQUE DE TYPE KAITAI ----------------------- */
+
+
+/* Sélection d'un type selon un contexte (instance) */
+struct _GKaitaiSwitch
+{
+ GKaitaiParser parent; /* A laisser en premier */
+
+ char *target; /* Source de bascule */
+
+ switch_case_t **cases; /* Choix de types potentiels */
+ size_t count; /* Quantité de ces choix */
+
+ switch_case_t *defcase; /* Choix par défaut ou NULL */
+
+ GKaitaiAttribute *generic; /* Attribut à dériver */
+
+};
+
+/* Sélection d'un type selon un contexte (classe) */
+struct _GKaitaiSwitchClass
+{
+ GKaitaiParserClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une sélection dynamique de type Kaitai. */
+bool g_kaitai_switch_create(GKaitaiSwitch *, GYamlNode *, GKaitaiAttribute *);
+
+
+
+#endif /* PLUGINS_KAITAI_PARSERS_SWITCH_INT_H */
diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c
new file mode 100644
index 0000000..6cfc96b
--- /dev/null
+++ b/plugins/kaitai/parsers/switch.c
@@ -0,0 +1,644 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * switch.h - gestion des énumérations Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "switch.h"
+
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include <common/extstr.h>
+#include <common/sort.h>
+#include <core/logs.h>
+#include <plugins/yaml/pair.h>
+
+
+#include "switch-int.h"
+#include "../expression.h"
+
+
+
+/* ------------------------ BASCULE DYNAMIQUE SELON CONTEXTE ------------------------ */
+
+
+/* Construit une valeur d'énumération à partir d'indications. */
+static switch_case_t *build_switch_case(const GYamlNode *, bool *);
+
+/* Supprime de la mémoire une bascule selon contexte. */
+static void delete_switch_case(switch_case_t *);
+
+/* Détermine si le cas correspond à une valeur de bascule. */
+static const char *is_suitable_switch_case_for_bytes(const switch_case_t *, const resolved_value_t *);
+
+/* Détermine si le cas correspond à une valeur de bascule. */
+static const char *is_suitable_switch_case_for_integer(const switch_case_t *, kaitai_scope_t *, const resolved_value_t *);
+
+
+
+/* ----------------------- SELECTION DYNAMIQUE DE TYPE KAITAI ----------------------- */
+
+
+/* Initialise la classe des sélections dynamiques de types. */
+static void g_kaitai_switch_class_init(GKaitaiSwitchClass *);
+
+/* Initialise une sélection dynamique de type Kaitai. */
+static void g_kaitai_switch_init(GKaitaiSwitch *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_switch_dispose(GKaitaiSwitch *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_switch_finalize(GKaitaiSwitch *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* BASCULE DYNAMIQUE SELON CONTEXTE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud Yaml à venir lire. *
+* defcase = indique si une valeur par défaut est visée. [OUT] *
+* *
+* Description : Construit une valeur d'énumération à partir d'indications. *
+* *
+* Retour : Structure de valeur mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static switch_case_t *build_switch_case(const GYamlNode *node, bool *defcase)
+{
+ switch_case_t *result; /* Enregistrement à retourner */
+ const char *key; /* Clef d'une conversion */
+ const char *value; /* Valeur Yaml particulière */
+
+ result = NULL;
+
+ if (!G_IS_YAML_PAIR(node))
+ goto exit;
+
+ key = g_yaml_pair_get_key(G_YAML_PAIR(node));
+ value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+ if (value == NULL)
+ goto exit;
+
+ result = malloc(sizeof(switch_case_t));
+
+ result->value = strdup(key);
+ result->type = strdup(value);
+
+ *defcase = (strcmp(key, "_") == 0);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : swcase = valeur à traiter. *
+* *
+* Description : Supprime de la mémoire une bascule selon contexte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+*****************************************************************************/
+
+static void delete_switch_case(switch_case_t *swcase)
+{
+ free(swcase->value);
+
+ free(swcase->type);
+
+ free(swcase);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : swcase = valeur à analyser. *
+* value = valeur à comparer. *
+* *
+* Description : Détermine si le cas correspond à une valeur de bascule. *
+* *
+* Retour : Type à utiliser ou NULL si aucune correspondance établie. *
+* *
+* Remarques : - *
+* *
+*****************************************************************************/
+
+static const char *is_suitable_switch_case_for_bytes(const switch_case_t *swcase, const resolved_value_t *value)
+{
+ const char *result; /* Désignation à retourner */
+ sized_string_t key; /* Changement de format */
+ bool valid; /* Validité des opérations */
+ int ret; /* Bilan d'une comparaison */
+
+ result = NULL;
+
+ key.data = swcase->value;
+ key.len = strlen(swcase->value);
+
+ valid = (key.len > 2);
+
+ if (valid)
+ valid = (swcase->value[0] == '"' || swcase->value[0] == '\'');
+
+ if (valid)
+ {
+ valid = (key.data[0] == key.data[key.len - 1]);
+
+ key.data++;
+ key.len -= 2;
+
+ }
+
+ if (valid)
+ {
+ if (value->type == GVT_BYTES)
+ {
+ ret = szmemcmp(&key, &value->bytes);
+
+ if (ret == 0)
+ result = swcase->type;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : swcase = valeur à analyser. *
+* locals = variables locales pour les résolutions de types. *
+* value = valeur à comparer. *
+* *
+* Description : Détermine si le cas correspond à une valeur de bascule. *
+* *
+* Retour : Type à utiliser ou NULL si aucune correspondance établie. *
+* *
+* Remarques : - *
+* *
+*****************************************************************************/
+
+static const char *is_suitable_switch_case_for_integer(const switch_case_t *swcase, kaitai_scope_t *locals, const resolved_value_t *value)
+{
+ const char *result; /* Désignation à retourner */
+ bool valid; /* Validité des opérations */
+ resolved_value_t key; /* Changement de format */
+ unsigned long long unsigned_conv; /* Valeur convertie #1 */
+ long long signed_conv; /* Valeur convertie #2 */
+
+ result = NULL;
+
+ valid = (swcase->value[0] != '"' && swcase->value[0] != '\'');
+
+ if (valid)
+ {
+ if (strchr(swcase->value, ':') != NULL)
+ {
+ valid = resolve_kaitai_expression_as_integer(locals, swcase->value, strlen(swcase->value), &key);
+
+ if (valid)
+ {
+ if (key.type == GVT_UNSIGNED_INTEGER)
+ {
+ if (value->type == GVT_UNSIGNED_INTEGER)
+ {
+ if (key.unsigned_integer == value->unsigned_integer)
+ result = swcase->type;
+ }
+ else
+ {
+ if (key.unsigned_integer == value->signed_integer)
+ result = swcase->type;
+ }
+ }
+ else
+ {
+ if (value->type == GVT_UNSIGNED_INTEGER)
+ {
+ if (key.signed_integer == value->unsigned_integer)
+ result = swcase->type;
+ }
+ else
+ {
+ if (key.signed_integer == value->signed_integer)
+ result = swcase->type;
+ }
+ }
+
+ }
+
+ }
+
+ else
+ {
+ if (value->type == GVT_UNSIGNED_INTEGER)
+ {
+ unsigned_conv = strtoull(swcase->value, NULL, 0);
+
+ valid = (errno != ERANGE && errno != EINVAL);
+
+ if (valid && unsigned_conv == value->unsigned_integer)
+ result = swcase->type;
+
+ }
+ else
+ {
+ signed_conv = strtoll(swcase->value, NULL, 0);
+
+ valid = (errno != ERANGE && errno != EINVAL);
+
+ if (valid && signed_conv == value->signed_integer)
+ result = swcase->type;
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SELECTION DYNAMIQUE DE TYPE KAITAI */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un choix dynamique de type Kaitai. */
+G_DEFINE_TYPE(GKaitaiSwitch, g_kaitai_switch, G_TYPE_KAITAI_PARSER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des sélections dynamiques de types. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_switch_class_init(GKaitaiSwitchClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GKaitaiParserClass *parser; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_switch_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_switch_finalize;
+
+ parser = G_KAITAI_PARSER_CLASS(klass);
+
+ parser->parse = (parse_kaitai_fc)g_kaitai_switch_parse_content;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kswitch = instance à initialiser. *
+* *
+* Description : Initialise une sélection dynamique de type Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_switch_init(GKaitaiSwitch *kswitch)
+{
+ kswitch->target = NULL;
+
+ kswitch->cases = NULL;
+ kswitch->count = 0;
+
+ kswitch->defcase = NULL;
+
+ kswitch->generic = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kswitch = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_switch_dispose(GKaitaiSwitch *kswitch)
+{
+ g_clear_object(&kswitch->generic);
+
+ G_OBJECT_CLASS(g_kaitai_switch_parent_class)->dispose(G_OBJECT(kswitch));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kswitch = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_switch_finalize(GKaitaiSwitch *kswitch)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (kswitch->target != NULL)
+ free(kswitch->target);
+
+ for (i = 0; i < kswitch->count; i++)
+ delete_switch_case(kswitch->cases[i]);
+
+ if (kswitch->cases != NULL)
+ free(kswitch->cases);
+
+ if (kswitch->defcase != NULL)
+ delete_switch_case(kswitch->defcase);
+
+ G_OBJECT_CLASS(g_kaitai_switch_parent_class)->finalize(G_OBJECT(kswitch));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = noeud Yaml contenant l'attribut à constituer. *
+* generic = lecteur d'attribut Kaitai à dériver. *
+* *
+* Description : Construit une sélection dynamique de type Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiSwitch *g_kaitai_switch_new(GYamlNode *parent, GKaitaiAttribute *generic)
+{
+ GKaitaiSwitch *result; /* Identifiant à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_SWITCH, NULL);
+
+ if (!g_kaitai_switch_create(result, parent, generic))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kswitch = sélectionneur de type à initialiser pleinement. *
+* parent = noeud Yaml contenant l'attribut à constituer. *
+* generic = lecteur d'attribut Kaitai à dériver. *
+* *
+* Description : Met en place une sélection dynamique de type Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAttribute *generic)
+{
+ bool result; /* Bilan à retourner */
+ GYamlNode *node; /* Noeud de définition */
+ GYamlNode *subnode; /* Noeud de précisions */
+ const char *value; /* Valeur Yaml particulière */
+ GYamlNode *collec; /* Liste de noeuds à traiter */
+ GYamlNode **subnodes; /* Eventuels noeuds trouvés */
+ size_t count; /* Quantité de ces noeuds */
+ size_t i; /* Boucle de parcours */
+ bool defcase; /* Définition par défaut ? */
+ switch_case_t *swcase; /* Bascule à noter */
+
+ result = false;
+
+ node = g_yaml_node_find_first_by_path(parent, "/type/");
+ if (node == NULL) goto exit;
+
+ /* Source de la bascule */
+
+ subnode = g_yaml_node_find_first_by_path(node, "/switch-on");
+ assert(G_IS_YAML_PAIR(subnode));
+
+ value = g_yaml_pair_get_value(G_YAML_PAIR(subnode));
+ if (value == NULL)
+ {
+ g_object_unref(G_OBJECT(subnode));
+ goto bad_definition;
+ }
+
+ kswitch->target = strdup(value);
+
+ g_object_unref(G_OBJECT(subnode));
+
+ /* Conditions de bascule */
+
+ collec = g_yaml_node_find_first_by_path(node, "/cases/");
+ if (collec == NULL) goto bad_definition;
+ if (!G_IS_YAML_COLLEC(collec)) goto bad_definition;
+
+ subnodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+
+ g_object_unref(G_OBJECT(collec));
+
+ if (count == 0) goto bad_definition;
+
+ for (i = 0; i < count; i++)
+ {
+ swcase = build_switch_case(subnodes[i], &defcase);
+ if (swcase == NULL) break;
+
+ g_object_unref(G_OBJECT(subnodes[i]));
+
+ kswitch->cases = realloc(kswitch->cases, ++kswitch->count * sizeof(switch_case_t *));
+ kswitch->cases[kswitch->count - 1] = swcase;
+
+ }
+
+ result = (i == count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(subnodes[i]));
+
+ if (subnodes != NULL)
+ free(subnodes);
+
+ /* Fin des procédures */
+
+ if (result)
+ {
+ kswitch->generic = generic;
+ g_object_ref(G_OBJECT(generic));
+ }
+
+ bad_definition:
+
+ g_object_unref(G_OBJECT(node));
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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. *
+* 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_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
+{
+ bool result; /* Bilan à retourner */
+ 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 = true;
+
+ final_type = NULL;
+
+ /* 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_integer(kswitch->cases[i], locals, &value);
+
+ if (final_type != NULL)
+ goto next_step;
+
+ }
+
+ status = resolve_kaitai_expression_as_bytes(locals, kswitch->target, strlen(kswitch->target), &value);
+
+ /* Tenative n°1 : version "chaîne" */
+
+ 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;
+
+ }
+
+ 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, epos, record);
+
+ g_object_unref(G_OBJECT(attrib));
+
+ }
+
+ return true;
+ return result;
+
+}
diff --git a/plugins/kaitai/parsers/switch.h b/plugins/kaitai/parsers/switch.h
new file mode 100644
index 0000000..c45237a
--- /dev/null
+++ b/plugins/kaitai/parsers/switch.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * switch.h - prototypes pour la gestion des énumérations Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PARSERS_SWITCH_H
+#define _PLUGINS_KAITAI_PARSERS_SWITCH_H
+
+
+#include <glib-object.h>
+
+
+#include <plugins/yaml/node.h>
+
+
+#include "attribute.h"
+
+
+
+#define G_TYPE_KAITAI_SWITCH g_kaitai_switch_get_type()
+#define G_KAITAI_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_SWITCH, GKaitaiSwitch))
+#define G_IS_KAITAI_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_SWITCH))
+#define G_KAITAI_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_SWITCH, GKaitaiSwitchClass))
+#define G_IS_KAITAI_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_SWITCH))
+#define G_KAITAI_SWITCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_SWITCH, GKaitaiSwitchClass))
+
+
+/* Sélection d'un type selon un contexte (instance) */
+typedef struct _GKaitaiSwitch GKaitaiSwitch;
+
+/* Sélection d'un type selon un contexte (classe) */
+typedef struct _GKaitaiSwitchClass GKaitaiSwitchClass;
+
+
+/* Indique le type défini pour un choix dynamique de type Kaitai. */
+GType g_kaitai_switch_get_type(void);
+
+/* Construit une sélection dynamique de type Kaitai. */
+GKaitaiSwitch *g_kaitai_switch_new(GYamlNode *, GKaitaiAttribute *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_SWITCH_H */
diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h
new file mode 100644
index 0000000..535ce57
--- /dev/null
+++ b/plugins/kaitai/parsers/type-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type-int.h - prototypes internes pour la définition d'un type particulier pour Kaitai
+ *
+ * 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_PARSERS_TYPE_INT_H
+#define PLUGINS_KAITAI_PARSERS_TYPE_INT_H
+
+
+#include "struct-int.h"
+#include "type.h"
+
+
+
+/* Définition d'un type particulier nouveau pour Kaitai (instance) */
+struct _GKaitaiType
+{
+ GKaitaiStruct parent; /* A laisser en premier */
+
+ char *name; /* Nom du type particulier */
+
+};
+
+/* Définition d'un type particulier nouveau pour Kaitai (classe) */
+struct _GKaitaiTypeClass
+{
+ GKaitaiStructClass parent; /* A laisser en premier */
+
+};
+
+
+/* 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/yaml/reader.c b/plugins/kaitai/parsers/type.c
index eebc02b..81efbeb 100644
--- a/plugins/yaml/reader.c
+++ b/plugins/kaitai/parsers/type.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * reader.c - lecteur de contenu Yaml
+ * struct.c - définition d'une structure Kaitai
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,61 +21,42 @@
*/
-#include "reader.h"
+#include "type.h"
#include <malloc.h>
#include <string.h>
-#include <gio/gio.h>
+#include <plugins/yaml/pair.h>
-#include "line.h"
+#include "type-int.h"
+#include "../parser.h"
-/* Lecteur de contenu Yaml (instance) */
-struct _GYamlReader
-{
- GObject parent; /* A laisser en premier */
-
- GYamlLine **lines; /* Lignes Yaml chargées */
- size_t count; /* Quantié de ces lignes */
-
- GYamlTree *tree; /* Arborescence constituée */
-
-};
-
-/* Lecteur de contenu Yaml (classe) */
-struct _GYamlReaderClass
-{
- GObjectClass parent; /* A laisser en premier */
+/* Initialise la classe des types particuliers pour Kaitai. */
+static void g_kaitai_type_class_init(GKaitaiTypeClass *);
-};
-
-
-/* Initialise la classe des lecteurs de contenus Yaml. */
-static void g_yaml_reader_class_init(GYamlReaderClass *);
-
-/* Initialise une instance de lecteur de contenu Yaml. */
-static void g_yaml_reader_init(GYamlReader *);
+/* Initialise un type particulier pour Kaitai. */
+static void g_kaitai_type_init(GKaitaiType *);
/* Supprime toutes les références externes. */
-static void g_yaml_reader_dispose(GYamlReader *);
+static void g_kaitai_type_dispose(GKaitaiType *);
/* Procède à la libération totale de la mémoire. */
-static void g_yaml_reader_finalize(GYamlReader *);
+static void g_kaitai_type_finalize(GKaitaiType *);
-/* Indique le type défini pour un lecteur de contenu Yaml. */
-G_DEFINE_TYPE(GYamlReader, g_yaml_reader, G_TYPE_OBJECT);
+/* Indique le type défini pour un type particulier pour Kaitai. */
+G_DEFINE_TYPE(GKaitaiType, g_kaitai_type, G_TYPE_KAITAI_STRUCT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des lecteurs de contenus Yaml. *
+* Description : Initialise la classe des types particuliers pour Kaitai. *
* *
* Retour : - *
* *
@@ -83,23 +64,23 @@ G_DEFINE_TYPE(GYamlReader, g_yaml_reader, G_TYPE_OBJECT);
* *
******************************************************************************/
-static void g_yaml_reader_class_init(GYamlReaderClass *klass)
+static void g_kaitai_type_class_init(GKaitaiTypeClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_yaml_reader_dispose;
- object->finalize = (GObjectFinalizeFunc)g_yaml_reader_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_type_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_type_finalize;
}
/******************************************************************************
* *
-* Paramètres : reader = instance à initialiser. *
+* Paramètres : kstruct = instance à initialiser. *
* *
-* Description : Initialise une instance de lecteur de contenu Yaml. *
+* Description : Initialise un type particulier pour Kaitai. *
* *
* Retour : - *
* *
@@ -107,19 +88,16 @@ static void g_yaml_reader_class_init(GYamlReaderClass *klass)
* *
******************************************************************************/
-static void g_yaml_reader_init(GYamlReader *reader)
+static void g_kaitai_type_init(GKaitaiType *type)
{
- reader->lines = NULL;
- reader->count = 0;
-
- reader->tree = NULL;
+ type->name = NULL;
}
/******************************************************************************
* *
-* Paramètres : reader = instance d'objet GLib à traiter. *
+* Paramètres : type = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -129,23 +107,16 @@ static void g_yaml_reader_init(GYamlReader *reader)
* *
******************************************************************************/
-static void g_yaml_reader_dispose(GYamlReader *reader)
+static void g_kaitai_type_dispose(GKaitaiType *type)
{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < reader->count; i++)
- g_clear_object(&reader->lines[i]);
-
- g_clear_object(&reader->tree);
-
- G_OBJECT_CLASS(g_yaml_reader_parent_class)->dispose(G_OBJECT(reader));
+ G_OBJECT_CLASS(g_kaitai_type_parent_class)->dispose(G_OBJECT(type));
}
/******************************************************************************
* *
-* Paramètres : reader = instance d'objet GLib à traiter. *
+* Paramètres : type = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -155,22 +126,21 @@ static void g_yaml_reader_dispose(GYamlReader *reader)
* *
******************************************************************************/
-static void g_yaml_reader_finalize(GYamlReader *reader)
+static void g_kaitai_type_finalize(GKaitaiType *type)
{
- if (reader->lines != NULL)
- free(reader->lines);
+ if (type->name != NULL)
+ free(type->name);
- G_OBJECT_CLASS(g_yaml_reader_parent_class)->finalize(G_OBJECT(reader));
+ G_OBJECT_CLASS(g_kaitai_type_parent_class)->finalize(G_OBJECT(type));
}
/******************************************************************************
* *
-* Paramètres : content = données brutes au format Yaml à charger. *
-* length = quantité de ces données. *
+* Paramètres : parent = noeud Yaml contenant l'attribut à constituer. *
* *
-* Description : Crée un lecteur pour contenu au format Yaml. *
+* Description : Construit un lecteur de type pour Kaitai. *
* *
* Retour : Instance mise en place ou NULL en cas d'échec. *
* *
@@ -178,135 +148,92 @@ static void g_yaml_reader_finalize(GYamlReader *reader)
* *
******************************************************************************/
-GYamlReader *g_yaml_reader_new_from_content(const char *content, size_t length)
+GKaitaiType *g_kaitai_type_new(GYamlNode *parent)
{
- GYamlReader *result; /* Structure à retourner */
- char *dumped; /* Contenu manipulable */
- char *saved; /* Sauvegarde de position */
- char *iter; /* Boucle de parcours */
- size_t number; /* Indice de ligne courante */
- GYamlLine *line; /* Nouvelle ligne Yaml */
-
- result = g_object_new(G_TYPE_YAML_READER, NULL);
-
- dumped = malloc(length * sizeof(char));
-
- memcpy(dumped, content, length);
-
- for (iter = dumped, saved = strchr(iter, '\n'), number = 0;
- *iter != '\0';
- iter = ++saved, saved = strchr(iter, '\n'), number++)
- {
- if (saved != NULL)
- *saved = '\0';
-
- if (*iter != '\0')
- {
- line = g_yaml_line_new(iter, number);
-
- if (line == NULL)
- goto format_error;
-
- result->lines = realloc(result->lines, ++result->count * sizeof(GYamlLine *));
-
- g_object_ref_sink(G_OBJECT(line));
- result->lines[result->count - 1] = line;
-
- }
-
- if (saved == NULL)
- break;
+ GKaitaiType *result; /* Structure à retourner */
- }
+ result = g_object_new(G_TYPE_KAITAI_TYPE, NULL);
- free(dumped);
-
- result->tree = g_yaml_tree_new(result->lines, result->count);
+ if (!g_kaitai_type_create(result, parent))
+ g_clear_object(&result);
return result;
- format_error:
-
- g_object_unref(G_OBJECT(result));
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : path = chemin d'accès à un contenu à charger. *
+* Paramètres : type = lecteur de type Kaitai à initialiser pleinement. *
+* parent = noeud Yaml contenant l'attribut à constituer. *
* *
-* Description : Crée un lecteur pour contenu au format Yaml. *
+* Description : Met en place un lecteur de type pour Kaitai. *
* *
-* Retour : Instance mise en place ou NULL en cas d'échec. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlReader *g_yaml_reader_new_from_path(const char *path)
+bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent)
{
- GYamlReader *result; /* Structure à retourner */
- char *scheme; /* Préfixe d'URI identifié */
- GFile *file; /* Accès au contenu visé */
- GFileInputStream *stream; /* Flux ouvert en lecture */
- GFileInfo *info; /* Informations du flux */
- size_t length; /* Quantité d'octets présents */
- char *content; /* Données obtenues par lecture*/
-
- result = NULL;
+ bool result; /* Bilan à retourner */
+ const char *name; /* Désignation du type */
+ char *sub_path; /* Chemin d'accès suivant */
+ GYamlNode *sub; /* Contenu Yaml d'un type */
- /* Ouverture du fichier */
+ result = false;
- scheme = g_uri_parse_scheme(path);
+ /* Extraction du nom */
- if (scheme != NULL)
- {
- g_free(scheme);
- file = g_file_new_for_uri(path);
- }
+ if (!G_IS_YAML_PAIR(parent))
+ goto exit;
- else
- file = g_file_new_for_path(path);
+ name = g_yaml_pair_get_key(G_YAML_PAIR(parent));
- stream = g_file_read(file, NULL, NULL);
+ type->name = strdup(name);
- if (stream == NULL)
- goto no_content;
+ /* Extraction des bases du type */
- /* Détermination de sa taille */
+ asprintf(&sub_path, "/%s/", name);
+ sub = g_yaml_node_find_first_by_path(parent, sub_path);
+ free(sub_path);
- info = g_file_input_stream_query_info(stream, G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, NULL);
+ if (sub == NULL)
+ goto exit;
- if (info == NULL)
- goto no_size_info;
+ result = g_kaitai_structure_create(G_KAITAI_STRUCT(type), sub);
- length = g_file_info_get_size(info);
+ g_object_unref(G_OBJECT(sub));
- /* Lecture des données */
+ exit:
- content = malloc(length + 1 * sizeof(char));
-
- if (!g_input_stream_read_all(G_INPUT_STREAM(stream), content, length, (gsize []) { 0 }, NULL, NULL))
- goto read_error;
-
- content[length] = '\0';
-
- result = g_yaml_reader_new_from_content(content, length + 1);
+ return result;
- read_error:
+}
- free(content);
- no_size_info:
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
- g_object_unref(G_OBJECT(stream));
+GKaitaiType *g_kaitai_type_new_as_import(const char *name, const char *filename)
+{
+ GKaitaiType *result; /* Structure à retourner */
- no_content:
+ result = g_object_new(G_TYPE_KAITAI_TYPE, NULL);
- g_object_unref(G_OBJECT(file));
+ if (!g_kaitai_type_create_as_import(result, name, filename))
+ g_clear_object(&result);
return result;
@@ -315,31 +242,29 @@ GYamlReader *g_yaml_reader_new_from_path(const char *path)
/******************************************************************************
* *
-* Paramètres : reader = lecteur de contenu Yaml à consulter. *
-* count = taille de la liste constituée. [OUT] *
+* Paramètres : type = lecteur de type Kaitai à initialiser pleinement. *
+* name = nom à attribuer au futur type. *
+* filename = chemin vers une définition Kaitai à charger. *
* *
-* Description : Fournit la liste des lignes lues depuis un contenu Yaml. *
+* Description : Met en place un lecteur de type externe pour Kaitai. *
* *
-* Retour : Liste de lignes correspondant au contenu Yaml lu. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlLine **g_yaml_reader_get_lines(const GYamlReader *reader, size_t *count)
+bool g_kaitai_type_create_as_import(GKaitaiType *type, const char *name, const char *filename)
{
- GYamlLine **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours */
+ bool result; /* Bilan à retourner */
- *count = reader->count;
+ /* Extraction du nom */
- result = malloc(*count * sizeof(GYamlLine *));
+ type->name = strdup(name);
- for (i = 0; i < *count; i++)
- {
- result[i] = reader->lines[i];
- g_object_ref(result[i]);
- }
+ /* Extraction des bases du type */
+
+ result = g_kaitai_structure_create_from_file(G_KAITAI_STRUCT(type), filename);
return result;
@@ -348,24 +273,21 @@ GYamlLine **g_yaml_reader_get_lines(const GYamlReader *reader, size_t *count)
/******************************************************************************
* *
-* Paramètres : reader = lecteur de contenu Yaml à consulter. *
+* Paramètres : type = définition de type particulier à consulter. *
* *
-* Description : Fournit l'arborescence associée à la lecture de lignes Yaml. *
+* Description : Indique le nom de scène du type représenté. *
* *
-* Retour : Arborescence constituée par la lecture du contenu Yaml. *
+* Retour : Désignation humaine. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlTree *g_yaml_reader_get_tree(const GYamlReader *reader)
+const char *g_kaitai_type_get_name(const GKaitaiType *type)
{
- GYamlTree *result; /* Arborescence à retourner */
-
- result = reader->tree;
+ const char *result; /* Nom à retourner */
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
+ result = type->name;
return result;
diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h
new file mode 100644
index 0000000..d19ab90
--- /dev/null
+++ b/plugins/kaitai/parsers/type.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - prototypes pour la définition d'un type particulier pour Kaitai
+ *
+ * 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_PARSERS_TYPE_H
+#define _PLUGINS_KAITAI_PARSERS_TYPE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <plugins/yaml/node.h>
+
+
+
+#define G_TYPE_KAITAI_TYPE g_kaitai_type_get_type()
+#define G_KAITAI_TYPE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TYPE, GKaitaiType))
+#define G_IS_KAITAI_TYPE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TYPE))
+#define G_KAITAI_TYPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TYPE, GKaitaiTypeClass))
+#define G_IS_KAITAI_TYPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TYPE))
+#define G_KAITAI_TYPE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TYPE, GKaitaiTypeClass))
+
+
+/* Définition d'un type particulier nouveau pour Kaitai (instance) */
+typedef struct _GKaitaiType GKaitaiType;
+
+/* Définition d'un type particulier nouveau pour Kaitai (classe) */
+typedef struct _GKaitaiTypeClass GKaitaiTypeClass;
+
+
+/* Indique le type défini pour un type particulier pour Kaitai. */
+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 *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PARSERS_TYPE_H */
diff --git a/plugins/kaitai/python/Makefile.am b/plugins/kaitai/python/Makefile.am
new file mode 100644
index 0000000..f222a66
--- /dev/null
+++ b/plugins/kaitai/python/Makefile.am
@@ -0,0 +1,26 @@
+
+noinst_LTLIBRARIES = libkaitaipython.la
+
+libkaitaipython_la_SOURCES = \
+ array.h array.c \
+ module.h module.c \
+ parser.h parser.c \
+ record.h record.c \
+ scope.h scope.c \
+ stream.h stream.c
+
+libkaitaipython_la_LIBADD = \
+ parsers/libkaitaipythonparsers.la \
+ records/libkaitaipythonrecords.la \
+ rost/libkaitaipythonrost.la
+
+libkaitaipython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipython_la_SOURCES:%c=)
+
+
+SUBDIRS = parsers records rost
diff --git a/plugins/kaitai/python/array.c b/plugins/kaitai/python/array.c
new file mode 100644
index 0000000..4973c76
--- /dev/null
+++ b/plugins/kaitai/python/array.c
@@ -0,0 +1,265 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.h - équivalent Python du fichier "plugins/kaitai/array.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "array.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../array-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_array, G_TYPE_KAITAI_ARRAY);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_array_init(PyObject *, PyObject *, PyObject *);
+
+/* Convertit un tableau Kaitai en série d'octets si possible. */
+static PyObject *py_kaitai_array___bytes__(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_array_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define KAITAI_ARRAY_DOC \
+ "KaitaiArray defines an array for collecting various Kaitai items." \
+ "\n" \
+ "Instances can be created using following constructor:\n" \
+ "\n" \
+ " KaitaiArray()" \
+ "\n" \
+ "In this implementation, arrays do not have to carry items all" \
+ " belonging to the same type. Access and conversions to bytes are" \
+ " handled and checked at runtime."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un binaire. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Convertit un tableau Kaitai en série d'octets si possible. *
+* *
+* Retour : Série d'octets ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_array___bytes__(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Représentation à renvoyer */
+ GKaitaiArray *array; /* Tableau à manipuler */
+ sized_string_t bytes; /* Version en série d'octets */
+ bool status; /* Bilan de la conversion */
+
+#define KAITAI_ARRAY_AS_BYTES_METHOD PYTHON_METHOD_DEF \
+( \
+ __bytes__, "$self, /", \
+ METH_NOARGS, py_kaitai_array, \
+ "Provide a bytes representation of the array, when possible" \
+ " and without implementing the Python buffer protocol.\n" \
+ "\n" \
+ "THe result is bytes or a *TypeError* exception is raised if" \
+ " the array is not suitable for a conversion to bytes." \
+)
+
+ array = G_KAITAI_ARRAY(pygobject_get(self));
+
+ status = g_kaitai_array_convert_to_bytes(array, &bytes);
+
+ if (status)
+ {
+ result = PyBytes_FromStringAndSize(bytes.data, bytes.len);
+ exit_szstr(&bytes);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to convert the Kaitai array to bytes");
+ result = NULL;
+ }
+
+ 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_kaitai_array_type(void)
+{
+ static PyMethodDef py_kaitai_array_methods[] = {
+ KAITAI_ARRAY_AS_BYTES_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_array_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_array_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.KaitaiArray",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_ARRAY_DOC,
+
+ .tp_methods = py_kaitai_array_methods,
+ .tp_getset = py_kaitai_array_getseters,
+
+ .tp_init = py_kaitai_array_init,
+ .tp_new = py_kaitai_array_new,
+
+ };
+
+ return &py_kaitai_array_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiArray. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_array_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'KaitaiArray' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_array_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ARRAY, 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 tableau d'éléments Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_array(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_array_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai array");
+ break;
+
+ case 1:
+ *((GKaitaiArray **)dst) = G_KAITAI_ARRAY(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/array.h b/plugins/kaitai/python/array.h
new file mode 100644
index 0000000..aeba541
--- /dev/null
+++ b/plugins/kaitai/python/array.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/array.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ARRAY_H
+#define _PLUGINS_KAITAI_PYTHON_ARRAY_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_array_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.KaitaiArray'. */
+bool ensure_python_kaitai_array_is_registered(void);
+
+/* Tente de convertir en tableau d'éléments Kaitai. */
+int convert_to_kaitai_array(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ARRAY_H */
diff --git a/plugins/kaitai/python/module.c b/plugins/kaitai/python/module.c
new file mode 100644
index 0000000..07fb962
--- /dev/null
+++ b/plugins/kaitai/python/module.c
@@ -0,0 +1,135 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire kaitai en tant que module
+ *
+ * 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 "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "array.h"
+#include "parser.h"
+#include "record.h"
+#include "scope.h"
+#include "stream.h"
+#include "parsers/module.h"
+#include "records/module.h"
+#include "rost/module.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.kaitai' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_DOC \
+ "kaitai is a module trying to reverse some of the effects produced by ProGuard.\n" \
+ "\n" \
+ "Its action is focused on reverting name obfuscation by running binary diffing against" \
+ " OpenSource packages from the AOSP."
+
+ static PyModuleDef py_chrysalide_kaitai_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.kaitai",
+ .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins");
+
+ module = build_python_module(super, &py_chrysalide_kaitai_module);
+
+ result = (module != NULL);
+
+ assert(result);
+
+ if (result) result = add_kaitai_parsers_module();
+ if (result) result = add_kaitai_records_module();
+ if (result) result = add_kaitai_rost_module();
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'plugins.kaitai'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_kaitai_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_kaitai_array_is_registered();
+ if (result) result = ensure_python_kaitai_parser_is_registered();
+ if (result) result = ensure_python_match_record_is_registered();
+ if (result) result = ensure_python_kaitai_scope_is_registered();
+ if (result) result = ensure_python_kaitai_stream_is_registered();
+
+ if (result) result = populate_kaitai_parsers_module();
+ if (result) result = populate_kaitai_records_module();
+ if (result) result = populate_kaitai_rost_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/module.h b/plugins/kaitai/python/module.h
new file mode 100644
index 0000000..939de07
--- /dev/null
+++ b/plugins/kaitai/python/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire kaitai en tant que module
+ *
+ * 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_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai' au module Python. */
+bool add_kaitai_module_to_python_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai'. */
+bool populate_kaitai_module(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_MODULE_H */
diff --git a/plugins/kaitai/python/parser.c b/plugins/kaitai/python/parser.c
new file mode 100644
index 0000000..067d3b0
--- /dev/null
+++ b/plugins/kaitai/python/parser.c
@@ -0,0 +1,205 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - équivalent Python du fichier "plugins/kaitai/parser.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 "parser.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../parser.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(kaitai_parser, G_TYPE_KAITAI_PARSER, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_parser_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_parser_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define KAITAI_PARSER_DOC \
+ "KaitaiParser is the class providing support for parsing binary contents" \
+ " using a special declarative language." \
+ "\n" \
+ "It is the Python bindings for a C implementation of the specifications" \
+ " described at http://kaitai.io/."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_parser_type(void)
+{
+ static PyMethodDef py_kaitai_parser_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_parser_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_parser_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.KaitaiParser",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_PARSER_DOC,
+
+ .tp_methods = py_kaitai_parser_methods,
+ .tp_getset = py_kaitai_parser_getseters,
+
+ .tp_init = py_kaitai_parser_init,
+ .tp_new = py_kaitai_parser_new,
+
+ };
+
+ return &py_kaitai_parser_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiParser.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_parser_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'KaitaiParser' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_parser_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_PARSER, 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 lecteur de données Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_parser(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_parser_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai parser");
+ break;
+
+ case 1:
+ *((GKaitaiParser **)dst) = G_KAITAI_PARSER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/yaml/python/reader.h b/plugins/kaitai/python/parser.h
index 19d238b..f4b6c96 100644
--- a/plugins/yaml/python/reader.h
+++ b/plugins/kaitai/python/parser.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * reader.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/reader.h"
+ * parser.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parser.h"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,8 +22,8 @@
*/
-#ifndef _PLUGINS_YAML_PYTHON_READER_H
-#define _PLUGINS_YAML_PYTHON_READER_H
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSER_H
+#define _PLUGINS_KAITAI_PYTHON_PARSER_H
#include <Python.h>
@@ -32,14 +32,14 @@
/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_yaml_reader_type(void);
+PyTypeObject *get_python_kaitai_parser_type(void);
-/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlReader'. */
-bool register_python_yaml_reader(PyObject *);
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.KaitaiParser'. */
+bool ensure_python_kaitai_parser_is_registered(void);
-/* Tente de convertir en lecteur de données au format Yaml. */
-int convert_to_yaml_reader(PyObject *, void *);
+/* Tente de convertir en lecteur de données Kaitai. */
+int convert_to_kaitai_parser(PyObject *, void *);
-#endif /* _PLUGINS_YAML_PYTHON_READER_H */
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSER_H */
diff --git a/plugins/kaitai/python/parsers/Makefile.am b/plugins/kaitai/python/parsers/Makefile.am
new file mode 100644
index 0000000..4c418af
--- /dev/null
+++ b/plugins/kaitai/python/parsers/Makefile.am
@@ -0,0 +1,19 @@
+
+noinst_LTLIBRARIES = libkaitaipythonparsers.la
+
+libkaitaipythonparsers_la_SOURCES = \
+ attribute.h attribute.c \
+ enum.h enum.c \
+ instance.h instance.c \
+ meta.h meta.c \
+ module.h module.c \
+ struct.h struct.c \
+ type.h type.c
+
+libkaitaipythonparsers_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonparsers_la_SOURCES:%c=)
diff --git a/plugins/kaitai/python/parsers/attribute.c b/plugins/kaitai/python/parsers/attribute.c
new file mode 100644
index 0000000..c2f3db6
--- /dev/null
+++ b/plugins/kaitai/python/parsers/attribute.c
@@ -0,0 +1,425 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.c - équivalent Python du fichier "plugins/kaitai/parsers/attribute.c"
+ *
+ * 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 "attribute.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../parser.h"
+#include "../../parsers/attribute-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_attribute, G_TYPE_KAITAI_ATTRIBUTE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_attribute_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique la désignation brute d'un identifiant Kaitai. */
+static PyObject *py_kaitai_attribute_get_raw_id(PyObject *, void *);
+
+/* Indique la désignation originelle d'un identifiant Kaitai. */
+static PyObject *py_kaitai_attribute_get_original_id(PyObject *, void *);
+
+/* Fournit une éventuelle documentation concernant l'attribut. */
+static PyObject *py_kaitai_attribute_get_doc(PyObject *, void *);
+
+/* Détermine si l'attribue porte une valeur entière signée. */
+static PyObject *py_kaitai_attribute_get_handle_signed_integer(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_kaitai_attribute_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GYamlNode *parent; /* Noeud Yaml de l'attribut */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiAttribute *attrib; /* Création GLib à transmettre */
+
+#define KAITAI_ATTRIBUTE_DOC \
+ "KaitaiAttribute is the class providing support for parsing binary" \
+ " contents using a special declarative language." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KaitaiAttribute(parent)" \
+ "\n" \
+ "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \
+ " to Yaml data to load.\n" \
+ "\n" \
+ "The class is the Python bindings for a C implementation of the Attribute" \
+ " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+ if (!g_kaitai_attribute_create(attrib, parent, true))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai attribute."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique la désignation brute d'un identifiant Kaitai. *
+* *
+* Retour : Valeur brute de l'identifiant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_raw_id(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiAttribute *attrib; /* Version native de l'attribut*/
+ const char *value; /* Valeur à transmettre */
+
+#define KAITAI_ATTRIBUTE_RAW_ID_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ raw_id, py_kaitai_attribute, \
+ "Raw value used by Kaitai to identify one attribute" \
+ " among others.\n" \
+ "\n" \
+ "The returned indentifier is a string value." \
+)
+
+ attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+ value = g_kaitai_attribute_get_raw_id(attrib);
+
+ if (value == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ result = PyUnicode_FromString(value);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique la désignation originelle d'un identifiant Kaitai. *
+* *
+* Retour : Valeur originelle de l'identifiant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_original_id(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiAttribute *attrib; /* Version native de l'attribut*/
+ const char *value; /* Valeur à transmettre */
+
+#define KAITAI_ATTRIBUTE_ORIGINAL_ID_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ original_id, py_kaitai_attribute, \
+ "Optional alternative identifier for the attribute, as seen in" \
+ " the original specifications.\n" \
+ "\n" \
+ "The returned value is a string or *None*." \
+)
+
+ attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+ value = g_kaitai_attribute_get_original_id(attrib);
+
+ if (value == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ result = PyUnicode_FromString(value);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit une éventuelle documentation concernant l'attribut. *
+* *
+* Retour : Description enregistrée ou None si absente. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_doc(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiAttribute *attrib; /* Version native de l'attribut*/
+ const char *doc; /* Documentation à transmettre */
+
+#define KAITAI_ATTRIBUTE_DOC_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ doc, py_kaitai_attribute, \
+ "Optional documentation for the attribute.\n" \
+ "\n" \
+ "The returned value is a string or *None*." \
+)
+
+ attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+ doc = g_kaitai_attribute_get_doc(attrib);
+
+ if (doc == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ result = PyUnicode_FromString(doc);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Détermine si l'attribue porte une valeur entière signée. *
+* *
+* Retour : Bilan de la consultation : True si un entier signé est visé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_handle_signed_integer(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiAttribute *attrib; /* Version native de l'attribut*/
+ bool status; /* Bilan d'une consultation */
+
+#define KAITAI_ATTRIBUTE_HANDLE_SIGNED_INTEGER_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ handle_signed_integer, py_kaitai_attribute, \
+ "Sign of the carried integer value, if any: positive or negative?\n" \
+ "\n" \
+ "This status is provided as a boolean value." \
+)
+
+ attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+ status = g_kaitai_attribute_handle_signed_integer(attrib);
+
+ result = status ? Py_True : Py_False;
+ 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_kaitai_attribute_type(void)
+{
+ static PyMethodDef py_kaitai_attribute_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_attribute_getseters[] = {
+ KAITAI_ATTRIBUTE_RAW_ID_ATTRIB,
+ KAITAI_ATTRIBUTE_ORIGINAL_ID_ATTRIB,
+ KAITAI_ATTRIBUTE_DOC_ATTRIB,
+ KAITAI_ATTRIBUTE_HANDLE_SIGNED_INTEGER_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_attribute_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiAttribute",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_ATTRIBUTE_DOC,
+
+ .tp_methods = py_kaitai_attribute_methods,
+ .tp_getset = py_kaitai_attribute_getseters,
+
+ .tp_init = py_kaitai_attribute_init,
+ .tp_new = py_kaitai_attribute_new,
+
+ };
+
+ return &py_kaitai_attribute_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....KaitaiAttribute. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_attribute_is_registered(void)
+{
+ PyTypeObject *type; /* Type 'KaitaiAttribute' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_attribute_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_kaitai_parser_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ATTRIBUTE, 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 attribut de données Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_attribute(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_attribute_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai attribute");
+ break;
+
+ case 1:
+ *((GKaitaiAttribute **)dst) = G_KAITAI_ATTRIBUTE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/attribute.h b/plugins/kaitai/python/parsers/attribute.h
new file mode 100644
index 0000000..931e769
--- /dev/null
+++ b/plugins/kaitai/python/parsers/attribute.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/attribute.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_PARSERS_ATTRIBUTE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_attribute_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiAttribute'. */
+bool ensure_python_kaitai_attribute_is_registered(void);
+
+/* Tente de convertir en attribut de données Kaitai. */
+int convert_to_kaitai_attribute(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H */
diff --git a/plugins/kaitai/python/parsers/enum.c b/plugins/kaitai/python/parsers/enum.c
new file mode 100644
index 0000000..9200c6f
--- /dev/null
+++ b/plugins/kaitai/python/parsers/enum.c
@@ -0,0 +1,468 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - équivalent Python du fichier "plugins/kaitai/parsers/enum.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 "enum.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../../parsers/enum-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_enum, G_TYPE_KAITAI_ENUM);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_enum_init(PyObject *, PyObject *, PyObject *);
+
+/* Traduit une étiquette brute en constante d'énumération. */
+static PyObject *py_kaitai_enum_find_value(PyObject *, PyObject *);
+
+/* Traduit une constante d'énumération en étiquette brute. */
+static PyObject *py_kaitai_enum_find_label(PyObject *, PyObject *);
+
+/* Traduit une constante d'énumération en documentation. */
+static PyObject *py_kaitai_enum_find_documentation(PyObject *, PyObject *);
+
+/* Fournit le nom principal d'une énumération. */
+static PyObject *py_kaitai_enum_get_name(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_kaitai_enum_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GYamlNode *parent; /* Noeud Yaml de l'attribut */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiEnum *kenum; /* Création GLib à transmettre */
+
+#define KAITAI_ENUM_DOC \
+ "The KaitaiEnum class maps integer constants to symbolic names using" \
+ " Kaitai definitions.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KaitaiEnum(parent)" \
+ "\n" \
+ "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \
+ " to Yaml data to load.\n" \
+ "\n" \
+ "The class is the Python bindings for a C implementation of the EnumSpec" \
+ " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+ if (!g_kaitai_enum_create(kenum, parent))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai enumeration."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = instance de l'énumération Kaitai à manipuler. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Traduit une étiquette brute en constante d'énumération. *
+* *
+* Retour : Valeur retrouvée ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_find_value(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ const char *label; /* Etiquette à rechercher */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiEnum *kenum; /* Enumération Kaitai courante */
+ sized_string_t cstr; /* CHaîne avec sa longueur */
+ bool status; /* Bilan de la conversion */
+ resolved_value_t value; /* valeur à transformer */
+
+#define KAITAI_ENUM_FIND_VALUE_METHOD PYTHON_METHOD_DEF \
+( \
+ find_value, "$self, label", \
+ METH_VARARGS, py_kaitai_enum, \
+ "Translate a given enumeration label into its relative value.\n" \
+ "\n" \
+ "The *label* argument is expected to be a string.\n" \
+ "\n" \
+ "The result is an integer or *None* in case of resolution failure." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &label);
+ if (!ret) return NULL;
+
+ kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+ cstr.data = (char *)label;
+ cstr.len = strlen(label);
+
+ status = g_kaitai_enum_find_value(kenum, &cstr, &value);
+
+ if (status)
+ {
+ if (value.type == GVT_UNSIGNED_INTEGER)
+ result = PyLong_FromUnsignedLongLong(value.unsigned_integer);
+ else
+ {
+ assert(value.type == GVT_SIGNED_INTEGER);
+ result = PyLong_FromLongLong(value.signed_integer);
+ }
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = instance de l'énumération Kaitai à manipuler. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Traduit une constante d'énumération en étiquette brute. *
+* *
+* Retour : Désignation ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_find_label(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ int prefix; /* Préfixe attendu ? */
+ resolved_value_t value; /* valeur à transformer */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiEnum *kenum; /* Enumération Kaitai courante */
+ char *label; /* Etiquette reconstruite */
+
+#define KAITAI_ENUM_FIND_LABEL_METHOD PYTHON_METHOD_DEF \
+( \
+ find_label, "$self, value, / , prefix=False", \
+ METH_VARARGS, py_kaitai_enum, \
+ "Provide the label linked to a constant value within the current" \
+ " enumeration.\n" \
+ "\n" \
+ "The *value* is a simple integer, and *prefix* is a boolean indicating" \
+ " if the result has to integrate the enumeration name as a prefix.\n" \
+ "\n" \
+ "The result is a string or *None* in case of resolution failure." \
+)
+
+ prefix = 0;
+
+ ret = PyArg_ParseTuple(args, "K|p", &value.unsigned_integer, prefix);
+ if (!ret) return NULL;
+
+ kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+ value.type = GVT_UNSIGNED_INTEGER;
+ label = g_kaitai_enum_find_label(kenum, &value, prefix);
+
+ if (label != NULL)
+ {
+ result = PyUnicode_FromString(label);
+ free(label);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = instance de l'énumération Kaitai à manipuler. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Traduit une constante d'énumération en documentation. *
+* *
+* Retour : Documentation associée à la valeur indiquée ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_find_documentation(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ resolved_value_t value; /* valeur à transformer */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiEnum *kenum; /* Enumération Kaitai courante */
+ char *doc; /* Documentation obtenue */
+
+#define KAITAI_ENUM_FIND_DOCUMENTATION_METHOD PYTHON_METHOD_DEF \
+( \
+ find_documentation, "$self, value", \
+ METH_VARARGS, py_kaitai_enum, \
+ "Provide the optional documentation linked to a constant value within" \
+ " the current enumeration.\n" \
+ "\n" \
+ "The *value* is a simple integer.\n" \
+ "\n" \
+ "The result is a string or *None* if no documentation is registered" \
+ " for the provided value." \
+)
+
+ ret = PyArg_ParseTuple(args, "K", &value.unsigned_integer);
+ if (!ret) return NULL;
+
+ kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+ value.type = GVT_UNSIGNED_INTEGER;
+ doc = g_kaitai_enum_find_documentation(kenum, &value);
+
+ if (doc != NULL)
+ {
+ result = PyUnicode_FromString(doc);
+ free(doc);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le nom principal d'une énumération. *
+* *
+* Retour : Désignation de l'énumération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiEnum *kenum; /* Version native de l'objet */
+ const char *name; /* Valeur à transmettre */
+
+#define KAITAI_ENUM_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_kaitai_enum, \
+ "Name of the enumeration group, as a string value." \
+)
+
+ kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+ name = g_kaitai_enum_get_name(kenum);
+
+ result = PyUnicode_FromString(name);
+
+ 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_kaitai_enum_type(void)
+{
+ static PyMethodDef py_kaitai_enum_methods[] = {
+ KAITAI_ENUM_FIND_VALUE_METHOD,
+ KAITAI_ENUM_FIND_LABEL_METHOD,
+ KAITAI_ENUM_FIND_DOCUMENTATION_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_enum_getseters[] = {
+ KAITAI_ENUM_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_enum_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiEnum",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = KAITAI_ENUM_DOC,
+
+ .tp_methods = py_kaitai_enum_methods,
+ .tp_getset = py_kaitai_enum_getseters,
+
+ .tp_init = py_kaitai_enum_init,
+ .tp_new = py_kaitai_enum_new
+
+ };
+
+ return &py_kaitai_enum_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiEnum. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_enum_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'KaitaiEnum' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_enum_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ENUM, 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 ensemble d'énumérations Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_enum(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_enum_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai enumeration");
+ break;
+
+ case 1:
+ *((GKaitaiEnum **)dst) = G_KAITAI_ENUM(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/enum.h b/plugins/kaitai/python/parsers/enum.h
new file mode 100644
index 0000000..7172e69
--- /dev/null
+++ b/plugins/kaitai/python/parsers/enum.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/enum.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_PARSERS_ENUM_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_enum_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiEnum'. */
+bool ensure_python_kaitai_enum_is_registered(void);
+
+/* Tente de convertir en ensemble d'énumérations Kaitai. */
+int convert_to_kaitai_enum(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H */
diff --git a/plugins/kaitai/python/parsers/instance.c b/plugins/kaitai/python/parsers/instance.c
new file mode 100644
index 0000000..d55b58c
--- /dev/null
+++ b/plugins/kaitai/python/parsers/instance.c
@@ -0,0 +1,280 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.h - équivalent Python du fichier "plugins/kaitai/parsers/instance.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 "instance.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "attribute.h"
+#include "../../parsers/instance-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_instance, G_TYPE_KAITAI_INSTANCE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_instance_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom attribué à une instance Kaitai. */
+static PyObject *py_kaitai_instance_get_name(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_kaitai_instance_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GYamlNode *parent; /* Noeud Yaml de l'attribut */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiInstance *attrib; /* Création GLib à transmettre */
+
+#define KAITAI_INSTANCE_DOC \
+ "KaitaiInstance is the class providing support for Kaitai computed" \
+ " values.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KaitaiInstance(parent)" \
+ "\n" \
+ "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \
+ " to Yaml data to load.\n" \
+ "\n" \
+ "The class is the Python bindings for a C implementation of the Instance" \
+ " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ attrib = G_KAITAI_INSTANCE(pygobject_get(self));
+
+ if (!g_kaitai_instance_create(attrib, parent))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai instance."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le nom attribué à une instance Kaitai. *
+* *
+* Retour : Désignation pointant l'instance. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_instance_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiInstance *inst; /* Version native de l'instance*/
+ const char *name; /* Désignation à transmettre */
+
+#define KAITAI_INSTANCE_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_kaitai_instance, \
+ "Name used by Kaitai to identify the instance" \
+ " among others.\n" \
+ "\n" \
+ "The returned indentifier is a string value." \
+)
+
+ inst = G_KAITAI_INSTANCE(pygobject_get(self));
+
+ name = g_kaitai_instance_get_name(inst);
+ assert(name != NULL);
+
+ result = PyUnicode_FromString(name);
+
+ 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_kaitai_instance_type(void)
+{
+ static PyMethodDef py_kaitai_instance_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_instance_getseters[] = {
+ KAITAI_INSTANCE_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_instance_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiInstance",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_INSTANCE_DOC,
+
+ .tp_methods = py_kaitai_instance_methods,
+ .tp_getset = py_kaitai_instance_getseters,
+
+ .tp_init = py_kaitai_instance_init,
+ .tp_new = py_kaitai_instance_new,
+
+ };
+
+ return &py_kaitai_instance_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....KaitaiInstance. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_instance_is_registered(void)
+{
+ PyTypeObject *type; /* Type 'KaitaiInstance' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_instance_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_kaitai_attribute_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_INSTANCE, 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 instance Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_instance(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_instance_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai instance");
+ break;
+
+ case 1:
+ *((GKaitaiInstance **)dst) = G_KAITAI_INSTANCE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/instance.h b/plugins/kaitai/python/parsers/instance.h
new file mode 100644
index 0000000..8a0a6cf
--- /dev/null
+++ b/plugins/kaitai/python/parsers/instance.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/instance.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_PARSERS_INSTANCE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_instance_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiInstance'. */
+bool ensure_python_kaitai_instance_is_registered(void);
+
+/* Tente de convertir en instance Kaitai. */
+int convert_to_kaitai_instance(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H */
diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c
new file mode 100644
index 0000000..0bd7bf9
--- /dev/null
+++ b/plugins/kaitai/python/parsers/meta.c
@@ -0,0 +1,414 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta.h - équivalent Python du fichier "plugins/kaitai/parsers/meta.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 "meta.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/yaml/python/node.h>
+
+
+#include "../../parsers/meta-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_meta, G_TYPE_KAITAI_META);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_meta_init(PyObject *, PyObject *, PyObject *);
+
+/* Fournit l'identifié associé à une définiton Kaitai. */
+static PyObject *py_kaitai_meta_get_id(PyObject *, void *);
+
+/* Fournit la désignation humaine d'une définiton Kaitai. */
+static PyObject *py_kaitai_meta_get_title(PyObject *, void *);
+
+/* Indique la liste des définitions à importer. */
+static PyObject *py_kaitai_meta_get_dependencies(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_meta_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GYamlNode *parent; /* Noeud Yaml de l'attribut */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiMeta *kmeta; /* Création GLib à transmettre */
+
+#define KAITAI_META_DOC \
+ "The KaitaiMeta class stores general information about a Kaitai definition,"\
+ " such as required imports or the default endianness for reading values.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KaitaiMeta(parent)" \
+ "\n" \
+ "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \
+ " to Yaml data to load.\n" \
+ "\n" \
+ "The class is the Python bindings for a C implementation of the MetaSpec" \
+ " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ kmeta = G_KAITAI_META(pygobject_get(self));
+
+ if (!g_kaitai_meta_create(kmeta, parent))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai global description."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit l'identifié associé à une définiton Kaitai. *
+* *
+* Retour : Identifiant de définition complète ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiMeta *meta; /* Version native de l'objet */
+ const char *id; /* Valeur à transmettre */
+
+#define KAITAI_META_ID_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ id, py_kaitai_meta, \
+ "Identifier for the Kaitai definition, as a string" \
+ " value or *None* if any." \
+)
+
+ meta = G_KAITAI_META(pygobject_get(self));
+
+ id = g_kaitai_meta_get_id(meta);
+
+ if (id != NULL)
+ result = PyUnicode_FromString(id);
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la désignation humaine d'une définiton Kaitai. *
+* *
+* Retour : Intitulé de définition ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiMeta *meta; /* Version native de l'objet */
+ const char *title; /* Valeur à transmettre */
+
+#define KAITAI_META_TITLE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ title, py_kaitai_meta, \
+ "Humain description for the Kaitai definition, as a" \
+ " string value or *None* if any." \
+)
+
+ meta = G_KAITAI_META(pygobject_get(self));
+
+ title = g_kaitai_meta_get_title(meta);
+
+ if (title != NULL)
+ result = PyUnicode_FromString(title);
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la désignation humaine d'une définiton Kaitai. *
+* *
+* Retour : Intitulé de définition ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiMeta *meta; /* Version native de l'objet */
+ SourceEndian endian; /* Valeur à transmettre */
+
+#define KAITAI_META_ENDIAN_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ endian, py_kaitai_meta, \
+ "Default endianness for the Kaitai definition, as a" \
+ " pychrysalide.analysis.BinContent.SourceEndian value." \
+)
+
+ meta = G_KAITAI_META(pygobject_get(self));
+
+ endian = g_kaitai_meta_get_endian(meta);
+
+ result = cast_with_constants_group_from_type(get_python_binary_content_type(), "SourceEndian", endian);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique la liste des définitions à importer. *
+* *
+* Retour : Liste de désignations de définitions, vide ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_dependencies(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiMeta *meta; /* Version native de l'objet */
+ const char * const *dependencies; /* Liste d'imports requis */
+ size_t count; /* Quantité de ces imports */
+ size_t i; /* Boucle de parcours */
+
+#define KAITAI_META_DEPENDENCIES_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ dependencies, py_kaitai_meta, \
+ "Tuple of all definitions to import for the current" \
+ " definition.\n" \
+ "\n" \
+ "The result may be an empty string list." \
+)
+
+ meta = G_KAITAI_META(pygobject_get(self));
+
+ dependencies = g_kaitai_meta_get_dependencies(meta, &count);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(result, i, PyUnicode_FromString(dependencies[i]));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_meta_type(void)
+{
+ static PyMethodDef py_kaitai_meta_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_meta_getseters[] = {
+ KAITAI_META_ID_ATTRIB,
+ KAITAI_META_TITLE_ATTRIB,
+ KAITAI_META_ENDIAN_ATTRIB,
+ KAITAI_META_DEPENDENCIES_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_meta_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiMeta",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = KAITAI_META_DOC,
+
+ .tp_methods = py_kaitai_meta_methods,
+ .tp_getset = py_kaitai_meta_getseters,
+
+ .tp_init = py_kaitai_meta_init,
+ .tp_new = py_kaitai_meta_new
+
+ };
+
+ return &py_kaitai_meta_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiMeta. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_meta_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'KaitaiMeta' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_meta_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_META, 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 description globale Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_meta(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_meta_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai global description");
+ break;
+
+ case 1:
+ *((GKaitaiMeta **)dst) = G_KAITAI_META(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/yaml/python/scalar.h b/plugins/kaitai/python/parsers/meta.h
index 3812bd7..383cad9 100644
--- a/plugins/yaml/python/scalar.h
+++ b/plugins/kaitai/python/parsers/meta.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * scalar.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/scalar.h"
+ * meta.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/meta.h"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,8 +22,8 @@
*/
-#ifndef _PLUGINS_YAML_PYTHON_SCALAR_H
-#define _PLUGINS_YAML_PYTHON_SCALAR_H
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_META_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_META_H
#include <Python.h>
@@ -32,14 +32,14 @@
/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_yaml_scalar_type(void);
+PyTypeObject *get_python_kaitai_meta_type(void);
-/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlScalar'. */
-bool register_python_yaml_scalar(PyObject *);
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiMeta'. */
+bool ensure_python_kaitai_meta_is_registered(void);
-/* Tente de convertir en noeud d'arborescence de format Yaml. */
-int convert_to_yaml_scalar(PyObject *, void *);
+/* Tente de convertir en description globale Kaitai. */
+int convert_to_kaitai_meta(PyObject *, void *);
-#endif /* _PLUGINS_YAML_PYTHON_SCALAR_H */
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_META_H */
diff --git a/plugins/kaitai/python/parsers/module.c b/plugins/kaitai/python/parsers/module.c
new file mode 100644
index 0000000..549f728
--- /dev/null
+++ b/plugins/kaitai/python/parsers/module.c
@@ -0,0 +1,124 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire parsers en tant que module
+ *
+ * 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 "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "attribute.h"
+#include "enum.h"
+#include "instance.h"
+#include "meta.h"
+#include "struct.h"
+#include "type.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.kaitai.parsers' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_parsers_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_PARSERS_DOC \
+ "This module provides implementation for several Kaitai" \
+ " definitions parsers."
+
+ static PyModuleDef py_chrysalide_kaitai_parsers_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.kaitai.parsers",
+ .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_PARSERS_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ module = build_python_module(super, &py_chrysalide_kaitai_parsers_module);
+
+ result = (module != NULL);
+
+ assert(result);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'plugins.kaitai.parsers'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_kaitai_parsers_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_kaitai_attribute_is_registered();
+ if (result) result = ensure_python_kaitai_enum_is_registered();
+ if (result) result = ensure_python_kaitai_instance_is_registered();
+ if (result) result = ensure_python_kaitai_meta_is_registered();
+ if (result) result = ensure_python_kaitai_structure_is_registered();
+ if (result) result = ensure_python_kaitai_type_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/module.h b/plugins/kaitai/python/parsers/module.h
new file mode 100644
index 0000000..d0fdd66
--- /dev/null
+++ b/plugins/kaitai/python/parsers/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire parsers en tant que module
+ *
+ * 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_PARSERS_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.parsers' au module Python. */
+bool add_kaitai_parsers_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.parsers'. */
+bool populate_kaitai_parsers_module(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H */
diff --git a/plugins/kaitai/python/parsers/struct.c b/plugins/kaitai/python/parsers/struct.c
new file mode 100644
index 0000000..900cd1b
--- /dev/null
+++ b/plugins/kaitai/python/parsers/struct.c
@@ -0,0 +1,376 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.h - équivalent Python du fichier "plugins/kaitai/struct.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 "struct.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+
+
+#include "../parser.h"
+#include "../../parsers/struct-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_structure, G_TYPE_KAITAI_STRUCT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_structure_init(PyObject *, PyObject *, PyObject *);
+
+/* Parcourt un contenu binaire selon une description Kaitai. */
+static PyObject *py_kaitai_structure_parse(PyObject *, PyObject *);
+
+/* Fournit la désignation humaine d'une définiton Kaitai. */
+static PyObject *py_kaitai_structure_get_meta(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_kaitai_structure_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *text; /* Contenu de règles à traiter */
+ const char *filename; /* Fichier de définitions */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiStruct *kstruct; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "text", "filename", NULL };
+
+#define KAITAI_STRUCT_DOC \
+ "KaitaiStruct is the class providing support for parsing binary contents" \
+ " using a special declarative language." \
+ "\n" \
+ "Instances can be created using one of the following constructors:\n" \
+ "\n" \
+ " KaitaiStruct(text=str)" \
+ "\n" \
+ " KaitaiStruct(filename=str)" \
+ "\n" \
+ "Where *text* is a string containg a markup content to parse; the" \
+ " *filename* argument is an alternative string for a path pointing to the" \
+ " same kind of content. This path can be a real filename or a resource" \
+ " URI." \
+ "\n" \
+ "It is the Python bindings for a C implementation of the specifications" \
+ " described at http://kaitai.io/."
+
+ /* Récupération des paramètres */
+
+ text = NULL;
+ filename = NULL;
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist, &text, &filename);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ kstruct = G_KAITAI_STRUCT(pygobject_get(self));
+
+ if (text != NULL)
+ {
+ if (!g_kaitai_structure_create_from_text(kstruct, text))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai structure."));
+ return -1;
+ }
+
+ }
+
+ else if (filename != NULL)
+ {
+ if (!g_kaitai_structure_create_from_file(kstruct, filename))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai structure."));
+ return -1;
+ }
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create empty Kaitai structure."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = instance de l'interpréteur Kaitai à manipuler. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Parcourt un contenu binaire selon une description Kaitai. *
+* *
+* Retour : Arborescence d'éléments rencontrés selon les spécifications. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_structure_parse(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ GBinContent *content; /* Contenu binaire à traiter */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiStruct *kstruct; /* Interpréteur Kaitai courant */
+ GMatchRecord *record; /* Ensemble de correspondances */
+
+#define KAITAI_STRUCTURE_PARSE_METHOD PYTHON_METHOD_DEF \
+( \
+ parse, "$self, content", \
+ METH_VARARGS, py_kaitai_structure, \
+ "Parse a binary content with the loaded specifications." \
+ "\n" \
+ "The content has to be a pychrysalide.analysis.BinContent instance.\n" \
+ "\n" \
+ "The result is *None* if the parsing failed, or a" \
+ " pychrysalide.plugins.kaitai.MatchRecord object for each attribute" \
+ " met." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+ if (!ret) return NULL;
+
+ kstruct = G_KAITAI_STRUCT(pygobject_get(self));
+
+ record = g_kaitai_structure_parse(kstruct, content);
+
+ if (record != NULL)
+ {
+ result = pygobject_new(G_OBJECT(record));
+ g_object_unref(G_OBJECT(record));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la désignation humaine d'une définiton Kaitai. *
+* *
+* Retour : Intitulé de définition OU None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_structure_get_meta(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiStruct *kstruct; /* Version native de l'objet */
+ GKaitaiMeta *meta; /* Informations à transmettre */
+
+#define KAITAI_STRUCTURE_META_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ meta, py_kaitai_structure, \
+ "Global description provided for the Kaitai definition, as a" \
+ " pychrysalide.plugins.kaitai.parsers.KaitaiMeta instance." \
+)
+
+ kstruct = G_KAITAI_STRUCT(pygobject_get(self));
+
+ meta = g_kaitai_structure_get_meta(kstruct);
+
+ if (meta != NULL)
+ {
+ result = pygobject_new(G_OBJECT(meta));
+ g_object_unref(G_OBJECT(meta));
+ }
+ 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_kaitai_structure_type(void)
+{
+ static PyMethodDef py_kaitai_structure_methods[] = {
+ KAITAI_STRUCTURE_PARSE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_structure_getseters[] = {
+ KAITAI_STRUCTURE_META_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_structure_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiStruct",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = KAITAI_STRUCT_DOC,
+
+ .tp_methods = py_kaitai_structure_methods,
+ .tp_getset = py_kaitai_structure_getseters,
+
+ .tp_init = py_kaitai_structure_init,
+ .tp_new = py_kaitai_structure_new
+
+ };
+
+ return &py_kaitai_structure_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiStruct.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_structure_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'KaitaiStruct' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_structure_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_kaitai_parser_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_STRUCT, 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 structure de données Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_structure(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_structure_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai structure");
+ break;
+
+ case 1:
+ *((GKaitaiStruct **)dst) = G_KAITAI_STRUCT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/struct.h b/plugins/kaitai/python/parsers/struct.h
new file mode 100644
index 0000000..872f744
--- /dev/null
+++ b/plugins/kaitai/python/parsers/struct.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/struct.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_PARSERS_STRUCT_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_structure_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiStruct'. */
+bool ensure_python_kaitai_structure_is_registered(void);
+
+/* Tente de convertir en structure de données Kaitai. */
+int convert_to_kaitai_structure(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H */
diff --git a/plugins/kaitai/python/parsers/type.c b/plugins/kaitai/python/parsers/type.c
new file mode 100644
index 0000000..64a3419
--- /dev/null
+++ b/plugins/kaitai/python/parsers/type.c
@@ -0,0 +1,278 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - équivalent Python du fichier "plugins/kaitai/parsers/type.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 "type.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "struct.h"
+#include "../../parsers/type-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_type, G_TYPE_KAITAI_TYPE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_type_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom de scène du type représenté. */
+static PyObject *py_kaitai_type_get_name(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_kaitai_type_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GYamlNode *parent; /* Noeud Yaml de l'attribut */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiType *attrib; /* Création GLib à transmettre */
+
+#define KAITAI_TYPE_DOC \
+ "The KaitaiType class provides support for user-defined type used in" \
+ " Kaitai definitions.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KaitaiType(parent)" \
+ "\n" \
+ "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing" \
+ " to Yaml data to load.\n" \
+ "\n" \
+ "The class is the Python bindings for a C implementation of the TypesSpec" \
+ " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ attrib = G_KAITAI_TYPE(pygobject_get(self));
+
+ if (!g_kaitai_type_create(attrib, parent))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai type."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le nom de scène du type représenté. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_type_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiType *type; /* Version native du type */
+ const char *name; /* Désignation à transmettre */
+
+#define KAITAI_TYPE_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_kaitai_type, \
+ "Name of the user-defined type, provided as a unique" \
+ " string value." \
+)
+
+ type = G_KAITAI_TYPE(pygobject_get(self));
+
+ name = g_kaitai_type_get_name(type);
+ assert(name != NULL);
+
+ result = PyUnicode_FromString(name);
+
+ 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_kaitai_type_type(void)
+{
+ static PyMethodDef py_kaitai_type_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_type_getseters[] = {
+ KAITAI_TYPE_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_type_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.parsers.KaitaiType",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_TYPE_DOC,
+
+ .tp_methods = py_kaitai_type_methods,
+ .tp_getset = py_kaitai_type_getseters,
+
+ .tp_init = py_kaitai_type_init,
+ .tp_new = py_kaitai_type_new,
+
+ };
+
+ return &py_kaitai_type_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....parsers.KaitaiType. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_type_is_registered(void)
+{
+ PyTypeObject *type; /* Type 'KaitaiType' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_type_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_kaitai_structure_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TYPE, 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 type particulier pour Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_type(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_type_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai type");
+ break;
+
+ case 1:
+ *((GKaitaiType **)dst) = G_KAITAI_TYPE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/type.h b/plugins/kaitai/python/parsers/type.h
new file mode 100644
index 0000000..320bc71
--- /dev/null
+++ b/plugins/kaitai/python/parsers/type.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/type.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_type_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiType'. */
+bool ensure_python_kaitai_type_is_registered(void);
+
+/* Tente de convertir en type particulier pour Kaitai. */
+int convert_to_kaitai_type(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H */
diff --git a/plugins/yaml/python/line.c b/plugins/kaitai/python/record.c
index 11898d2..4194a9a 100644
--- a/plugins/yaml/python/line.c
+++ b/plugins/kaitai/python/record.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * line.c - équivalent Python du fichier "plugins/yaml/line.c"
+ * record.h - équivalent Python du fichier "plugins/kaitai/record.h"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,126 +22,106 @@
*/
-#include "line.h"
+#include "record.h"
#include <pygobject.h>
+#include <plugins/pychrysalide/access.h>
#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
-#include "../line.h"
+#include "parser.h"
+#include "../record.h"
-/* Crée un nouvel objet Python de type 'YamlLine'. */
-static PyObject *py_yaml_line_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(match_record, G_TYPE_MATCH_RECORD, NULL);
-/* Fournit la taille de l'indentation d'une ligne Yaml. */
-static PyObject *py_yaml_line_get_indent(PyObject *, void *);
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_match_record_init(PyObject *, PyObject *, PyObject *);
-/* Indique si la ligne représente un élément de liste. */
-static PyObject *py_yaml_line_is_list_item(PyObject *, void *);
+/* Modifie la référence au créateur de la correspondance. */
+static int py_match_record_set_creator(PyObject *, PyObject *, void *);
-/* Fournit la charge utile associée à une ligne Yaml. */
-static PyObject *py_yaml_line_get_payload(PyObject *, void *);
+/* Renvoie vers le lecteur à l'origine de la correspondance. */
+static PyObject *py_match_record_get_creator(PyObject *, void *);
-/* Fournit la clef associée à une ligne Yaml si elle existe. */
-static PyObject *py_yaml_line_get_key(PyObject *, void *);
+/* Fournit le contenu lié à une correspondance établie. */
+static PyObject *py_match_record_get_content(PyObject *, void *);
-/* Fournit la valeur associée à une ligne Yaml si elle existe. */
-static PyObject *py_yaml_line_get_value(PyObject *, void *);
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static PyObject *py_match_record_get_range(PyObject *, void *);
+
+/* Lit les octets bruts couverts par une correspondance. */
+static PyObject *py_match_record_get_raw_bytes(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'YamlLine'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_line_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_match_record_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
- const char *raw; /* Données Yaml brutes */
- Py_ssize_t index; /* Indice de ligne associée */
int ret; /* Bilan de lecture des args. */
- GYamlLine *line; /* Création GLib à transmettre */
-
-#define YAML_LINE_DOC \
- "YamlLine handles a line of Yaml data.\n" \
- "\n" \
- "The data may be a couple of key/value, a comment, aso.\n" \
- "\n" \
- "Instances can be created using the following constructor:\n" \
- "\n" \
- " YamlTree(raw, number)" \
- "\n" \
- "Where raw is a string providing raw data and number the index" \
- " of the line in the overall stream."
-
- ret = PyArg_ParseTuple(args, "sn", &raw, &index);
- if (!ret) return NULL;
-
- line = g_yaml_line_new(raw, index);
-
- if (line == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
- else
- {
- g_object_ref_sink(G_OBJECT(line));
- result = pygobject_new(G_OBJECT(line));
- g_object_unref(line);
- }
+#define MATCH_RECORD_DOC \
+ "MatchRecord is an abstract class providing mainly location and raw" \
+ " data of an area which has matched a part of a binary content."
- return result;
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
}
/******************************************************************************
* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
+* Paramètres : self = correspondance à manipuler. *
+* value = lecteur à l'origine de la correspondance. *
+* closure = adresse non utilisée ici. *
* *
-* Description : Fournit la taille de l'indentation d'une ligne Yaml. *
+* Description : Modifie la référence au créateur de la correspondance. *
* *
-* Retour : Taille de l'indentation rencontrée. *
+* Retour : Bilan de la définition. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_line_get_indent(PyObject *self, void *closure)
+static int py_match_record_set_creator(PyObject *self, PyObject *value, void *closure)
{
- PyObject *result; /* Résultat à retourner */
- GYamlLine *line; /* Version GLib du type */
- size_t indent; /* Taille de l'indentation */
-
-#define YAML_LINE_INDENT_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- indent, py_yaml_line, \
- "Quantity of characters used for the indentation." \
-)
+ int result; /* Bilan à renvoyer */
+ GMatchRecord *record; /* Version GLib de l'objet */
+ GKaitaiParser *parser; /* Lecteur à l'origine */
- line = G_YAML_LINE(pygobject_get(self));
+ record = G_MATCH_RECORD(pygobject_get(self));
- indent = g_yaml_line_count_indent(line);
+ if (!convert_to_kaitai_parser(value, &parser))
+ result = -1;
- result = PyLong_FromSize_t(indent);
+ else
+ {
+ g_match_record_fix_creator(record, parser);
+ result = 0;
+ }
return result;
@@ -150,35 +130,38 @@ static PyObject *py_yaml_line_get_indent(PyObject *self, void *closure)
/******************************************************************************
* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
+* Paramètres : self = correspondance à manipuler. *
+* closure = adresse non utilisée ici. *
* *
-* Description : Indique si la ligne représente un élément de liste. *
+* Description : Renvoie vers le lecteur à l'origine de la correspondance. *
* *
-* Retour : Statut de l'état lié à une liste d'éléments. *
+* Retour : Lecteur à l'origine de la création. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_line_is_list_item(PyObject *self, void *closure)
+static PyObject *py_match_record_get_creator(PyObject *self, void *closure)
{
- PyObject *result; /* Résultat à retourner */
- GYamlLine *line; /* Version GLib du type */
- bool status; /* Statut de la ligne */
-
-#define YAML_LINE_IS_LIST_ITEM_ATTRIB PYTHON_IS_DEF_FULL \
-( \
- list_item, py_yaml_line, \
- "Tell if the line starts a new list item." \
+ PyObject *result; /* Instance à retourner */
+ GMatchRecord *record; /* Version GLib de l'objet */
+ GKaitaiParser *parser; /* Lecteur à l'origine */
+
+#define MATCH_RECORD_CREATOR_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ creator, py_match_record, \
+ "Provide or define the pychrysalide.plugins.kaitai.KaitaiParser instance" \
+ " which has created the record.\n" \
+ "\n" \
+ "This field should not be defined after the record creation in most cases." \
)
- line = G_YAML_LINE(pygobject_get(self));
+ record = G_MATCH_RECORD(pygobject_get(self));
- status = g_yaml_line_is_list_item(line);
+ parser = g_match_record_get_creator(record);
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
+ result = pygobject_new(G_OBJECT(parser));
+ g_object_unref(parser);
return result;
@@ -190,31 +173,40 @@ static PyObject *py_yaml_line_is_list_item(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Fournit la charge utile associée à une ligne Yaml. *
+* Description : Fournit le contenu lié à une correspondance établie. *
* *
-* Retour : Contenu sous forme de chaîne de caractères. *
+* Retour : Contenu binaire associé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_line_get_payload(PyObject *self, void *closure)
+static PyObject *py_match_record_get_content(PyObject *self, void *closure)
{
- PyObject *result; /* Résultat à retourner */
- GYamlLine *line; /* Version GLib du type */
- const char *payload; /* Chaîne à transmettre */
-
-#define YAML_LINE_PAYLOAD_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- payload, py_yaml_line, \
- "Payload of the Yaml line." \
-)
+ PyObject *result; /* Valeur à retourner */
+ GMatchRecord *record; /* Conservation à consulter */
+ GBinContent *content; /* Contenu associé */
- line = G_YAML_LINE(pygobject_get(self));
+#define MATCH_RECORD_CONTENT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ content, py_match_record, \
+ "pychrysalide.analysis.BinContent instance linked to" \
+ " the match record." \
+)
- payload = g_yaml_line_get_payload(line);
+ record = G_MATCH_RECORD(pygobject_get(self));
+ content = g_match_record_get_content(record);
- result = PyUnicode_FromString(payload);
+ if (content != NULL)
+ {
+ result = pygobject_new(G_OBJECT(content));
+ g_object_unref(G_OBJECT(content));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
return result;
@@ -226,38 +218,33 @@ static PyObject *py_yaml_line_get_payload(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Fournit la clef associée à une ligne Yaml si elle existe. *
+* Description : Calcule ou fournit la zone couverte par une correspondance. *
* *
-* Retour : Clef sous forme de chaîne de caractères ou None. *
+* Retour : Zone de couverture déterminée. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_line_get_key(PyObject *self, void *closure)
+static PyObject *py_match_record_get_range(PyObject *self, void *closure)
{
- PyObject *result; /* Résultat à retourner */
- GYamlLine *line; /* Version GLib du type */
- const char *key; /* Chaîne à transmettre */
-
-#define YAML_LINE_KEY_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- key, py_yaml_line, \
- "Key linked to the Yaml line or None." \
-)
-
- line = G_YAML_LINE(pygobject_get(self));
+ PyObject *result; /* Valeur à retourner */
+ GMatchRecord *record; /* Conservation à consulter */
+ mrange_t range; /* Couverture courante */
- key = g_yaml_line_get_key(line);
+#define MATCH_RECORD_RANGE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ range, py_match_record, \
+ "Area of the matched data for the parsed attribute" \
+ " against a given binary content.\n" \
+ "\n" \
+ "This property is a pychrysalide.arch.mrange instance." \
+)
- if (key == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
+ record = G_MATCH_RECORD(pygobject_get(self));
+ g_match_record_get_range(record, &range);
- else
- result = PyUnicode_FromString(key);
+ result = build_from_internal_mrange(&range);
return result;
@@ -269,38 +256,33 @@ static PyObject *py_yaml_line_get_key(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Fournit la valeur associée à une ligne Yaml si elle existe. *
+* Description : Lit les octets bruts couverts par une correspondance. *
* *
-* Retour : Valeur sous forme de chaîne de caractères ou None. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_line_get_value(PyObject *self, void *closure)
+static PyObject *py_match_record_get_raw_bytes(PyObject *self, void *closure)
{
- PyObject *result; /* Résultat à retourner */
- GYamlLine *line; /* Version GLib du type */
- const char *value; /* Chaîne à transmettre */
-
-#define YAML_LINE_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- value, py_yaml_line, \
- "Value linked to the Yaml line or None." \
-)
+ PyObject *result; /* Valeur à retourner */
+ GMatchRecord *record; /* Conservation à consulter */
+ bin_t *out; /* Données brutes à transmettre*/
+ size_t len; /* Quantité de ces données */
- line = G_YAML_LINE(pygobject_get(self));
+#define MATCH_RECORD_RAW_BYTES_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ raw_bytes, py_match_record, \
+ "Raw bytes from the area covered by the record." \
+)
- value = g_yaml_line_get_value(line);
+ record = G_MATCH_RECORD(pygobject_get(self));
- if (value == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
+ g_match_record_read_raw_bytes(record, &out, &len);
- else
- result = PyUnicode_FromString(value);
+ result = PyBytes_FromStringAndSize((char *)out, len);
+ free(out);
return result;
@@ -319,48 +301,49 @@ static PyObject *py_yaml_line_get_value(PyObject *self, void *closure)
* *
******************************************************************************/
-PyTypeObject *get_python_yaml_line_type(void)
+PyTypeObject *get_python_match_record_type(void)
{
- static PyMethodDef py_yaml_line_methods[] = {
+ static PyMethodDef py_match_record_methods[] = {
{ NULL }
};
- static PyGetSetDef py_yaml_line_getseters[] = {
- YAML_LINE_INDENT_ATTRIB,
- YAML_LINE_IS_LIST_ITEM_ATTRIB,
- YAML_LINE_PAYLOAD_ATTRIB,
- YAML_LINE_KEY_ATTRIB,
- YAML_LINE_VALUE_ATTRIB,
+ static PyGetSetDef py_match_record_getseters[] = {
+ MATCH_RECORD_CREATOR_ATTRIB,
+ MATCH_RECORD_CONTENT_ATTRIB,
+ MATCH_RECORD_RANGE_ATTRIB,
+ MATCH_RECORD_RAW_BYTES_ATTRIB,
{ NULL }
};
- static PyTypeObject py_yaml_line_type = {
+ static PyTypeObject py_match_record_type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pychrysalide.plugins.yaml.YamlLine",
+ .tp_name = "pychrysalide.plugins.kaitai.MatchRecord",
.tp_basicsize = sizeof(PyGObject),
- .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = MATCH_RECORD_DOC,
- .tp_doc = YAML_LINE_DOC,
+ .tp_methods = py_match_record_methods,
+ .tp_getset = py_match_record_getseters,
- .tp_methods = py_yaml_line_methods,
- .tp_getset = py_yaml_line_getseters,
- .tp_new = py_yaml_line_new
+ .tp_init = py_match_record_init,
+ .tp_new = py_match_record_new,
};
- return &py_yaml_line_type;
+ return &py_match_record_type;
}
/******************************************************************************
* *
-* Paramètres : module = module dont la définition est à compléter. *
+* Paramètres : - *
* *
-* Description : Prend en charge l'objet 'pychrysalide.plugins.....YamlLine. *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...MatchRecord. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -368,17 +351,24 @@ PyTypeObject *get_python_yaml_line_type(void)
* *
******************************************************************************/
-bool register_python_yaml_line(PyObject *module)
+bool ensure_python_match_record_is_registered(void)
{
- PyTypeObject *type; /* Type Python 'YamlLine' */
+ PyTypeObject *type; /* Type Python 'MatchRecord' */
+ PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- type = get_python_yaml_line_type();
+ type = get_python_match_record_type();
- dict = PyModule_GetDict(module);
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai");
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_LINE, type, &PyGObject_Type))
- return false;
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_MATCH_RECORD, type))
+ return false;
+
+ }
return true;
@@ -390,7 +380,7 @@ bool register_python_yaml_line(PyObject *module)
* 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 ligne de données au format Yaml. *
+* Description : Tente de convertir en conservation de correspondance. *
* *
* Retour : Bilan de l'opération, voire indications supplémentaires. *
* *
@@ -398,11 +388,11 @@ bool register_python_yaml_line(PyObject *module)
* *
******************************************************************************/
-int convert_to_yaml_line(PyObject *arg, void *dst)
+int convert_to_match_record(PyObject *arg, void *dst)
{
int result; /* Bilan à retourner */
- result = PyObject_IsInstance(arg, (PyObject *)get_python_yaml_line_type());
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_match_record_type());
switch (result)
{
@@ -412,11 +402,11 @@ int convert_to_yaml_line(PyObject *arg, void *dst)
break;
case 0:
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Yaml line");
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to match record");
break;
case 1:
- *((GYamlLine **)dst) = G_YAML_LINE(pygobject_get(arg));
+ *((GMatchRecord **)dst) = G_MATCH_RECORD(pygobject_get(arg));
break;
default:
diff --git a/plugins/yaml/python/tree.h b/plugins/kaitai/python/record.h
index df9d5b8..edf75fc 100644
--- a/plugins/yaml/python/tree.h
+++ b/plugins/kaitai/python/record.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * tree.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/tree.h"
+ * record.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/record.h"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,8 +22,8 @@
*/
-#ifndef _PLUGINS_YAML_PYTHON_TREE_H
-#define _PLUGINS_YAML_PYTHON_TREE_H
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORD_H
+#define _PLUGINS_KAITAI_PYTHON_RECORD_H
#include <Python.h>
@@ -32,14 +32,14 @@
/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_yaml_tree_type(void);
+PyTypeObject *get_python_match_record_type(void);
-/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlTree'. */
-bool register_python_yaml_tree(PyObject *);
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.MatchRecord'. */
+bool ensure_python_match_record_is_registered(void);
-/* Tente de convertir en arborescence de lignes au format Yaml. */
-int convert_to_yaml_tree(PyObject *, void *);
+/* Tente de convertir en conservation de correspondance. */
+int convert_to_match_record(PyObject *, void *);
-#endif /* _PLUGINS_YAML_PYTHON_TREE_H */
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORD_H */
diff --git a/plugins/kaitai/python/records/Makefile.am b/plugins/kaitai/python/records/Makefile.am
new file mode 100644
index 0000000..3a3c672
--- /dev/null
+++ b/plugins/kaitai/python/records/Makefile.am
@@ -0,0 +1,19 @@
+
+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
+
+libkaitaipythonrecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonrecords_la_SOURCES:%c=)
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/delayed.c b/plugins/kaitai/python/records/delayed.c
new file mode 100644
index 0000000..32e3db1
--- /dev/null
+++ b/plugins/kaitai/python/records/delayed.c
@@ -0,0 +1,341 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.c - équivalent Python du fichier "plugins/kaitai/parsers/delayed.c"
+ *
+ * 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 "delayed.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 <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../scope.h"
+#include "../parsers/instance.h"
+#include "../../records/delayed-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_delayed, G_TYPE_RECORD_DELAYED);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_delayed_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_delayed_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_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. */
+ GRecordDelayed *delayed; /* Création GLib à transmettre */
+
+#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" \
+ " 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." \
+ " 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 */
+
+ content = NULL;
+
+ ret = PyArg_ParseTuple(args, "O&O&|O&",
+ convert_to_kaitai_instance, &inst,
+ convert_to_kaitai_scope, &locals,
+ convert_to_binary_content_or_none, &content);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ delayed = G_RECORD_DELAYED(pygobject_get(self));
+
+ if (!g_record_delayed_create(delayed, inst, locals, content))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record delayed."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_delayed_get_value(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ 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_DELAYED_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ value, py_record_delayed, \
+ "Carried value (as integer, bytes), or None in case of error." \
+)
+
+ result = NULL;
+
+ delayed = G_RECORD_DELAYED(pygobject_get(self));
+
+ status = g_record_delayed_compute_and_aggregate_value(delayed, &resolved);
+
+ if (status)
+ switch (resolved.type)
+ {
+ case GVT_ERROR:
+ assert(false);
+ PyErr_Format(PyExc_RuntimeError,
+ _("Error got while parsing Kaitai definition should not have been exported!"));
+ result = NULL;
+ break;
+
+ case GVT_UNSIGNED_INTEGER:
+ result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer);
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ result = PyLong_FromLongLong(resolved.signed_integer);
+ break;
+
+ case GVT_FLOAT:
+ result = PyFloat_FromDouble(resolved.floating_number);
+ break;
+
+ case GVT_BOOLEAN:
+ result = resolved.status ? Py_True : Py_False;
+ Py_INCREF(result);
+ break;
+
+ case GVT_BYTES:
+ result = PyBytes_FromStringAndSize(resolved.bytes.data, resolved.bytes.len);
+ exit_szstr(&resolved.bytes);
+ break;
+
+ case GVT_ARRAY:
+ result = pygobject_new(G_OBJECT(resolved.array));
+ break;
+
+ case GVT_RECORD:
+ result = pygobject_new(G_OBJECT(resolved.record));
+ break;
+
+ case GVT_STREAM:
+ result = pygobject_new(G_OBJECT(resolved.stream));
+ 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_delayed_type(void)
+{
+ static PyMethodDef py_record_delayed_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_record_delayed_getseters[] = {
+ RECORD_DELAYED_VALUE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_record_delayed_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordDelayed",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = RECORD_DELAYED_DOC,
+
+ .tp_methods = py_record_delayed_methods,
+ .tp_getset = py_record_delayed_getseters,
+
+ .tp_init = py_record_delayed_init,
+ .tp_new = py_record_delayed_new,
+
+ };
+
+ return &py_record_delayed_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide..records.RecordDelayed.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_record_delayed_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordDelayed' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_record_delayed_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_DELAYED, 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 valeur calculée. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_record_delayed(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_delayed_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 delayed");
+ break;
+
+ case 1:
+ *((GRecordDelayed **)dst) = G_RECORD_DELAYED(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/records/delayed.h b/plugins/kaitai/python/records/delayed.h
new file mode 100644
index 0000000..ba2d23a
--- /dev/null
+++ b/plugins/kaitai/python/records/delayed.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/delayed.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_DELAYED_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_delayed_type(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_delayed(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H */
diff --git a/plugins/kaitai/python/records/empty.c b/plugins/kaitai/python/records/empty.c
new file mode 100644
index 0000000..9861a39
--- /dev/null
+++ b/plugins/kaitai/python/records/empty.c
@@ -0,0 +1,286 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.c - équivalent Python du fichier "plugins/kaitai/parsers/empty.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "empty.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 "../parser.h"
+#include "../record.h"
+#include "../../records/empty-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_empty, G_TYPE_RECORD_EMPTY);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_empty_init(PyObject *, PyObject *, PyObject *);
+
+/* Produit une absence de valeur pour la correspondance. */
+static PyObject *py_record_empty_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_empty_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GKaitaiParser *parser; /* Analyseur défini créateur */
+ GBinContent *content; /* Contenu binaire manipulé */
+ vmpa2t *pos; /* Tête de lecture courante */
+ int ret; /* Bilan de lecture des args. */
+ GRecordEmpty *empty; /* Création GLib à transmettre */
+
+#define RECORD_EMPTY_DOC \
+ "The RecordEmpty object reflects absolutely no match and should only get" \
+ " in some rare cases.\n" \
+ "\n" \
+ "Instances can be created using following constructor:\n" \
+ "\n" \
+ " RecordEmpty(parser, content, pos)" \
+ "\n" \
+ "Where *parser* is the creator of the record, as a" \
+ " pychrysalide.plugins.kaitai.KaitaiParser instance, *content* is a" \
+ " pychrysalide.analysis.BinContent instance providing the processed data" \
+ " and *pos* defines the current reading location, as a" \
+ " pychrysalide.arch.vmpa value."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&O&O&",
+ convert_to_kaitai_parser, &parser,
+ convert_to_binary_content, &content,
+ convert_any_to_vmpa, &pos);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ empty = G_RECORD_EMPTY(pygobject_get(self));
+
+ if (!g_record_empty_create(empty, parser, content, pos))
+ {
+ clean_vmpa_arg(pos);
+
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+ return -1;
+
+ }
+
+ clean_vmpa_arg(pos);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Produit une absence de valeur pour la correspondance. *
+* *
+* Retour : None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_record_empty_get_value(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+
+#define RECORD_EMPTY_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ value, py_record_empty, \
+ "Always *None*.\n" \
+ "\n" \
+ "This attribute is only provided to mimic other" \
+ " record types." \
+)
+
+ 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_empty_type(void)
+{
+ static PyMethodDef py_record_empty_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_record_empty_getseters[] = {
+ RECORD_EMPTY_VALUE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_record_empty_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordEmpty",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = RECORD_EMPTY_DOC,
+
+ .tp_methods = py_record_empty_methods,
+ .tp_getset = py_record_empty_getseters,
+
+ .tp_init = py_record_empty_init,
+ .tp_new = py_record_empty_new,
+
+ };
+
+ return &py_record_empty_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...records.RecordEmpty. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_record_empty_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordEmpty' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_record_empty_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_EMPTY, 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 zone de correspondance vide. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_record_empty(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_empty_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 empty");
+ break;
+
+ case 1:
+ *((GRecordEmpty **)dst) = G_RECORD_EMPTY(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/records/empty.h b/plugins/kaitai/python/records/empty.h
new file mode 100644
index 0000000..ecd5fc9
--- /dev/null
+++ b/plugins/kaitai/python/records/empty.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/empty.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_EMPTY_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_EMPTY_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_empty_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordEmpty'. */
+bool ensure_python_record_empty_is_registered(void);
+
+/* Tente de convertir en zone de correspondance vide. */
+int convert_to_record_empty(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_EMPTY_H */
diff --git a/plugins/kaitai/python/records/group.c b/plugins/kaitai/python/records/group.c
new file mode 100644
index 0000000..a050043
--- /dev/null
+++ b/plugins/kaitai/python/records/group.c
@@ -0,0 +1,305 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.h - équivalent Python du fichier "plugins/kaitai/parsers/group.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "group.h"
+
+
+#include <pygobject.h>
+#include <string.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 <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../parsers/struct.h"
+#include "../../records/group-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_group, G_TYPE_RECORD_GROUP);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_group_init(PyObject *, PyObject *, PyObject *);
+
+/* Assure l'encadrement des accès aux champs d'une séquence. */
+static PyObject *py_record_group_getattr(PyObject *, char *);
+
+
+
+/******************************************************************************
+* *
+* 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_group_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GKaitaiStruct *kstruct; /* Séquence définie créatrice */
+ GBinContent *content; /* Contenu binaire analysé */
+ int ret; /* Bilan de lecture des args. */
+ GRecordGroup *group; /* Création GLib à transmettre */
+
+#define RECORD_GROUP_DOC \
+ "The RecordGroup class stores a map of parsed attributes with their" \
+ " relative values. Each of theses Kaitai attributes can be accessed as" \
+ " usual Python attribute.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " RecordGroup(kstruct, content)" \
+ "\n" \
+ "Where the *kstruct* refers to a" \
+ " pychrysalide.plugins.kaitai.parsers.KaitaiStructure instance as the" \
+ " creator of the newly created object, and *content* points to a" \
+ " pychrysalide.analysis.BinContent instance."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&O&",
+ convert_to_kaitai_structure, &kstruct,
+ convert_to_binary_content, &content);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ group = G_RECORD_GROUP(pygobject_get(self));
+
+ if (!g_record_group_create(group, kstruct, content))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record group."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = structure C convertie en Python. *
+* name = nom du champ auquel un accès est demandé. *
+* *
+* Description : Assure l'encadrement des accès aux champs d'une séquence. *
+* *
+* Retour : Valeur du champ demandé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_record_group_getattr(PyObject *self, char *name)
+{
+ PyObject *result; /* Elément à retourner */
+ GRecordGroup *group; /* Version native de l'objet */
+ GMatchRecord *found; /* Sous-élément identifié */
+ PyObject *w; /* Conversion du nom de champ */
+ PyTypeObject *tp; /* Type de l'objet manipulé */
+
+ group = G_RECORD_GROUP(pygobject_get(self));
+
+ found = g_match_record_find_by_name(G_MATCH_RECORD(group), name, strlen(name), DIRECT_SEARCH_DEEP_LEVEL);
+
+ if (found != NULL)
+ {
+ result = pygobject_new(G_OBJECT(found));
+ g_object_unref(G_OBJECT(found));
+ }
+
+ else
+ {
+ w = PyUnicode_InternFromString(name);
+ if (w == NULL) return NULL;
+
+ tp = Py_TYPE(self);
+
+ if (tp->tp_base->tp_getattro != NULL)
+ result = tp->tp_base->tp_getattro(self, w);
+
+ else
+ {
+ PyErr_Format(PyExc_AttributeError,
+ "type object '%.50s' has no attribute '%U'",
+ tp->tp_name, name);
+ result = NULL;
+ }
+
+ Py_DECREF(w);
+
+ }
+
+ 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_group_type(void)
+{
+ static PyMethodDef py_record_group_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_record_group_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_record_group_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordGroup",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_getattr = py_record_group_getattr,
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = RECORD_GROUP_DOC,
+
+ .tp_methods = py_record_group_methods,
+ .tp_getset = py_record_group_getseters,
+
+ .tp_init = py_record_group_init,
+ .tp_new = py_record_group_new,
+
+ };
+
+ return &py_record_group_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...records.RecordGroup. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_record_group_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordGroup' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_record_group_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_GROUP, 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 correspondances attribut/binaire. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_record_group(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_group_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 group");
+ break;
+
+ case 1:
+ *((GRecordGroup **)dst) = G_RECORD_GROUP(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/records/group.h b/plugins/kaitai/python/records/group.h
new file mode 100644
index 0000000..3e12ffc
--- /dev/null
+++ b/plugins/kaitai/python/records/group.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/group.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_GROUP_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_GROUP_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_group_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordGroup'. */
+bool ensure_python_record_group_is_registered(void);
+
+/* Tente de convertir en correspondances attribut/binaire. */
+int convert_to_record_group(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_GROUP_H */
diff --git a/plugins/kaitai/python/records/item.c b/plugins/kaitai/python/records/item.c
new file mode 100644
index 0000000..84c2c58
--- /dev/null
+++ b/plugins/kaitai/python/records/item.c
@@ -0,0 +1,394 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - équivalent Python du fichier "plugins/kaitai/parsers/item.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 "item.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 <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+#include "../../records/item-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_item, G_TYPE_RECORD_ITEM);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_item_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la série d'octets d'un élément Kaitai entier représenté. */
+static PyObject *py_record_item_get_truncated_bytes(PyObject *, void *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_item_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_item_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ 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. */
+ GRecordItem *item; /* Création GLib à transmettre */
+
+#define RECORD_ITEM_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 */
+
+ 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 */
+
+ item = G_RECORD_ITEM(pygobject_get(self));
+
+ if (!g_record_item_create(item, attrib, content, &range, endian))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record item."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Lit la série d'octets d'un élément Kaitai entier représenté. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_record_item_get_truncated_bytes(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GRecordItem *item; /* Version native de l'élément */
+ bool status; /* Bilan d'opération */
+ bin_t *out; /* Données brutes à transmettre*/
+ size_t len; /* Quantité de ces données */
+
+#define RECORD_ITEM_TRUNCATED_BYTES_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ truncated_bytes, py_record_item, \
+ "Raw bytes carried by the item (truncated if a separator" \
+ " is defined in the linked attribute), or None if irrelevant" \
+ " regarding to the type of the attribute." \
+)
+
+ item = G_RECORD_ITEM(pygobject_get(self));
+
+ status = g_record_item_get_truncated_bytes(item, &out, &len);
+
+ if (status)
+ {
+ result = PyBytes_FromStringAndSize((char *)out, len);
+ free(out);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_item_get_value(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GRecordItem *item; /* Version native de l'élément */
+ resolved_value_t resolved; /* Valeur sous forme générique */
+ bool status; /* Bilan d'opération */
+
+#define RECORD_ITEM_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ value, py_record_item, \
+ "Carried value (as integer, bytes), or None in case of error." \
+)
+
+ result = NULL;
+
+ item = G_RECORD_ITEM(pygobject_get(self));
+
+ status = g_record_item_get_value(item, &resolved);
+
+ if (status)
+ switch (resolved.type)
+ {
+ case GVT_ERROR:
+ assert(false);
+ PyErr_Format(PyExc_RuntimeError,
+ _("Error got while parsing Kaitai definition should not have been exported!"));
+ result = NULL;
+ break;
+
+ case GVT_UNSIGNED_INTEGER:
+ result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer);
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ result = PyLong_FromLongLong(resolved.signed_integer);
+ break;
+
+ case GVT_FLOAT:
+ result = PyFloat_FromDouble(resolved.floating_number);
+ break;
+
+ case GVT_BOOLEAN:
+ result = resolved.status ? Py_True : Py_False;
+ Py_INCREF(result);
+ break;
+
+ case GVT_BYTES:
+ result = PyBytes_FromStringAndSize(resolved.bytes.data, resolved.bytes.len);
+ exit_szstr(&resolved.bytes);
+ break;
+
+ case GVT_ARRAY:
+ result = pygobject_new(G_OBJECT(resolved.array));
+ break;
+
+ case GVT_RECORD:
+ result = pygobject_new(G_OBJECT(resolved.record));
+ break;
+
+ case GVT_STREAM:
+ result = pygobject_new(G_OBJECT(resolved.stream));
+ 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_item_type(void)
+{
+ static PyMethodDef py_record_item_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_record_item_getseters[] = {
+ RECORD_ITEM_TRUNCATED_BYTES_ATTRIB,
+ RECORD_ITEM_VALUE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_record_item_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordItem",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = RECORD_ITEM_DOC,
+
+ .tp_methods = py_record_item_methods,
+ .tp_getset = py_record_item_getseters,
+
+ .tp_init = py_record_item_init,
+ .tp_new = py_record_item_new,
+
+ };
+
+ return &py_record_item_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....records.RecordItem. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_record_item_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordItem' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_record_item_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_ITEM, 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_item(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_item_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 item");
+ break;
+
+ case 1:
+ *((GRecordItem **)dst) = G_RECORD_ITEM(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/yaml/python/line.h b/plugins/kaitai/python/records/item.h
index 00dcbd9..bde8a55 100644
--- a/plugins/yaml/python/line.h
+++ b/plugins/kaitai/python/records/item.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * line.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/line.h"
+ * item.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/item.h"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,8 +22,8 @@
*/
-#ifndef _PLUGINS_YAML_PYTHON_LINE_H
-#define _PLUGINS_YAML_PYTHON_LINE_H
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_ITEM_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_ITEM_H
#include <Python.h>
@@ -32,14 +32,14 @@
/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_yaml_line_type(void);
+PyTypeObject *get_python_record_item_type(void);
-/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlLine'. */
-bool register_python_yaml_line(PyObject *);
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordItem'. */
+bool ensure_python_record_item_is_registered(void);
-/* Tente de convertir en ligne de données au format Yaml. */
-int convert_to_yaml_line(PyObject *, void *);
+/* Tente de convertir en correspondance attribut/binaire. */
+int convert_to_record_item(PyObject *, void *);
-#endif /* _PLUGINS_YAML_PYTHON_LINE_H */
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_ITEM_H */
diff --git a/plugins/yaml/python/scalar.c b/plugins/kaitai/python/records/list.c
index 5a33cd1..d2eecbb 100644
--- a/plugins/yaml/python/scalar.c
+++ b/plugins/kaitai/python/records/list.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * scalar.c - équivalent Python du fichier "plugins/yaml/scalar.c"
+ * list.h - équivalent Python du fichier "plugins/kaitai/parsers/list.h"
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -22,71 +22,110 @@
*/
-#include "scalar.h"
+#include "list.h"
#include <pygobject.h>
+#include <string.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 <plugins/yaml/python/node.h>
-#include "collection.h"
-#include "line.h"
-#include "node.h"
-#include "../scalar.h"
+#include "../record.h"
+#include "../parsers/attribute.h"
+#include "../../records/list-int.h"
-/* Crée un nouvel objet Python de type 'YamlScalar'. */
-static PyObject *py_yaml_scalar_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(record_list, G_TYPE_RECORD_LIST);
-/* Attache une collection de noeuds Yaml à un noeud. */
-static int py_yaml_scalar_set_collection(PyObject *, PyObject *, void *);
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_list_init(PyObject *, PyObject *, PyObject *);
-/* Fournit une éventuelle collection rattachée à un noeud. */
-static PyObject *py_yaml_scalar_get_collection(PyObject *, void *);
+/* Dénombre le nombre de correspondances enregistrées. */
+static Py_ssize_t py_record_list_sq_length(PyObject *);
+
+/* Fournit un élément ciblé dans la liste de correspondances. */
+static PyObject *py_record_list_sq_item(PyObject *, Py_ssize_t);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'YamlScalar'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_scalar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_record_list_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
- GYamlLine *key; /* Ligne principale du noeud */
+ int result; /* Bilan à retourner */
+ GKaitaiAttribute *attrib; /* Attribut défini créateur */
+ GBinContent *content; /* Contenu binaire analysé */
+ vmpa2t *addr; /* Adresse de symbole à ajouter*/
int ret; /* Bilan de lecture des args. */
- GYamlScalar *node; /* Création GLib à transmettre */
+ GRecordList *list; /* Création GLib à transmettre */
+
+#define RECORD_LIST_DOC \
+ "The RecordList class collects a list of parsed attributes with their" \
+ " relative values. Each of theses Kaitai attributes can be accessed as" \
+ " subscriptable Python attribute.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " RecordList(content, attrib)" \
+ "\n" \
+ "Where the *attrib* argument refers to the" \
+ " pychrysalide.plugins.kaitai.parsers.KaitaiAttribute instance used to" \
+ " create each record contained by the list and *content* points to a" \
+ " pychrysalide.analysis.BinContent instance."
+
+ result = 0;
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&O&",
+ convert_to_kaitai_attribute, &attrib,
+ convert_to_binary_content, &content,
+ convert_any_to_vmpa, &addr);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1)
+ {
+ result = -1;
+ goto exit;
+ }
-#define YAML_SCALAR_DOC \
- "YamlScalar handles a scalar node in a Yaml tree.\n" \
- "\n" \
- "Instances can be created using the following constructor:\n" \
- "\n" \
- " YamlScalar(key)\n" \
- "\n" \
- "Where key is the main Yaml line for the scalar."
+ /* Eléments de base */
- ret = PyArg_ParseTuple(args, "O&", &convert_to_yaml_line, &key);
- if (!ret) return NULL;
+ list = G_RECORD_LIST(pygobject_get(self));
- node = g_yaml_scalar_new(key);
+ if (!g_record_list_create(list, attrib, content, addr))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record list."));
+ result = -1;
+ goto exit;
+ }
- g_object_ref_sink(G_OBJECT(node));
- result = pygobject_new(G_OBJECT(node));
- g_object_unref(node);
+ exit:
+
+ clean_vmpa_arg(addr);
return result;
@@ -95,44 +134,24 @@ static PyObject *py_yaml_scalar_new(PyTypeObject *type, PyObject *args, PyObject
/******************************************************************************
* *
-* Paramètres : self = contenu binaire à manipuler. *
-* value = collection de noeuds Yaml. *
-* closure = adresse non utilisée ici. *
+* Paramètres : self = instance Python manipulée. *
* *
-* Description : Attache une collection de noeuds Yaml à un noeud. *
+* Description : Dénombre le nombre de correspondances enregistrées. *
* *
-* Retour : Jeu d'attributs liés au contenu courant. *
+* Retour : Taille de la liste représentée. *
* *
* Remarques : - *
* *
******************************************************************************/
-static int py_yaml_scalar_set_collection(PyObject *self, PyObject *value, void *closure)
+static Py_ssize_t py_record_list_sq_length(PyObject *self)
{
- int result; /* Bilan à renvoyer */
- GYamlScalar *node; /* Version GLib du noeud */
- GYamlCollection *collec; /* Version GLib de la valeur */
-
- node = G_YAML_SCALAR(pygobject_get(self));
+ Py_ssize_t result; /* Quantité à retourner */
+ GRecordList *list; /* Version native de l'objet */
- if (value == Py_None)
- {
- g_yaml_scalar_set_collection(node, NULL);
- result = 0;
- }
+ list = G_RECORD_LIST(pygobject_get(self));
- else
- {
- if (!convert_to_yaml_collection(value, &collec))
- result = -1;
-
- else
- {
- g_yaml_scalar_set_collection(node, collec);
- result = 0;
- }
-
- }
+ result = g_record_list_count_records(list);
return result;
@@ -141,43 +160,36 @@ static int py_yaml_scalar_set_collection(PyObject *self, PyObject *value, void *
/******************************************************************************
* *
-* Paramètres : self = contenu binaire à manipuler. *
-* closure = adresse non utilisée ici. *
+* Paramètres : self = structure C convertie en Python. *
+* index = indice de la correspondance visée. *
* *
-* Description : Fournit une éventuelle collection rattachée à un noeud. *
+* Description : Fournit un élément ciblé dans la liste de correspondances. *
* *
-* Retour : Collection de noeuds Yaml ou None. *
+* Retour : Instance de correspondance particulière, voire None. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_scalar_get_collection(PyObject *self, void *closure)
+static PyObject *py_record_list_sq_item(PyObject *self, Py_ssize_t index)
{
PyObject *result; /* Instance à retourner */
- GYamlScalar *node; /* Version GLib du noeud */
- GYamlCollection *collec; /* Collection à transmettre */
-
-#define YAML_SCALAR_COLLECTION_ATTRIB PYTHON_GETSET_DEF_FULL \
-( \
- collection, py_yaml_scalar, \
- "Provide or define the collection of nodes attached to another Yaml node." \
-)
+ GRecordList *list; /* Version native de l'objet */
+ GMatchRecord *record; /* Correspondance retrouvée */
- node = G_YAML_SCALAR(pygobject_get(self));
+ list = G_RECORD_LIST(pygobject_get(self));
- collec = g_yaml_scalar_get_collection(node);
+ record = g_record_list_get_record(list, index);
- if (collec == NULL)
+ if (record != NULL)
{
- result = Py_None;
- Py_INCREF(result);
+ result = pygobject_new(G_OBJECT(record));
+ g_object_unref(G_OBJECT(record));
}
-
else
{
- result = pygobject_new(G_OBJECT(collec));
- g_object_unref(collec);
+ result = Py_None;
+ Py_INCREF(result);
}
return result;
@@ -197,44 +209,54 @@ static PyObject *py_yaml_scalar_get_collection(PyObject *self, void *closure)
* *
******************************************************************************/
-PyTypeObject *get_python_yaml_scalar_type(void)
+PyTypeObject *get_python_record_list_type(void)
{
- static PyMethodDef py_yaml_scalar_methods[] = {
+ static PySequenceMethods py_record_list_sequence_methods = {
+
+ .sq_length = py_record_list_sq_length,
+ .sq_item = py_record_list_sq_item,
+
+ };
+
+ static PyMethodDef py_record_list_methods[] = {
{ NULL }
};
- static PyGetSetDef py_yaml_scalar_getseters[] = {
- YAML_SCALAR_COLLECTION_ATTRIB,
+ static PyGetSetDef py_record_list_getseters[] = {
{ NULL }
};
- static PyTypeObject py_yaml_scalar_type = {
+ static PyTypeObject py_record_list_type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pychrysalide.plugins.yaml.YamlScalar",
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordList",
.tp_basicsize = sizeof(PyGObject),
- .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_as_sequence = &py_record_list_sequence_methods,
- .tp_doc = YAML_SCALAR_DOC,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_methods = py_yaml_scalar_methods,
- .tp_getset = py_yaml_scalar_getseters,
- .tp_new = py_yaml_scalar_new
+ .tp_doc = RECORD_LIST_DOC,
+
+ .tp_methods = py_record_list_methods,
+ .tp_getset = py_record_list_getseters,
+
+ .tp_init = py_record_list_init,
+ .tp_new = py_record_list_new,
};
- return &py_yaml_scalar_type;
+ return &py_record_list_type;
}
/******************************************************************************
* *
-* Paramètres : module = module dont la définition est à compléter. *
+* Paramètres : - *
* *
-* Description : Prend en charge l'objet 'pychrysalide.plugins.....YamlScalar.*
+* Description : Prend en charge l'objet 'pychrysalide....records.RecordList. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -242,17 +264,27 @@ PyTypeObject *get_python_yaml_scalar_type(void)
* *
******************************************************************************/
-bool register_python_yaml_scalar(PyObject *module)
+bool ensure_python_record_list_is_registered(void)
{
- PyTypeObject *type; /* Type Python 'YamlScalar' */
+ PyTypeObject *type; /* Type Python 'RecordList' */
+ PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- type = get_python_yaml_scalar_type();
+ type = get_python_record_list_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+ dict = PyModule_GetDict(module);
- dict = PyModule_GetDict(module);
+ if (!ensure_python_match_record_is_registered())
+ return false;
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_SCALAR, type, get_python_yaml_node_type()))
- return false;
+ if (!register_class_for_pygobject(dict, G_TYPE_RECORD_LIST, type))
+ return false;
+
+ }
return true;
@@ -264,7 +296,7 @@ bool register_python_yaml_scalar(PyObject *module)
* 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 noeud d'arborescence de format Yaml. *
+* Description : Tente de convertir en correspondance attribut/binaire. *
* *
* Retour : Bilan de l'opération, voire indications supplémentaires. *
* *
@@ -272,11 +304,11 @@ bool register_python_yaml_scalar(PyObject *module)
* *
******************************************************************************/
-int convert_to_yaml_scalar(PyObject *arg, void *dst)
+int convert_to_record_list(PyObject *arg, void *dst)
{
int result; /* Bilan à retourner */
- result = PyObject_IsInstance(arg, (PyObject *)get_python_yaml_scalar_type());
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_list_type());
switch (result)
{
@@ -286,11 +318,11 @@ int convert_to_yaml_scalar(PyObject *arg, void *dst)
break;
case 0:
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Yaml scalar");
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record list");
break;
case 1:
- *((GYamlScalar **)dst) = G_YAML_SCALAR(pygobject_get(arg));
+ *((GRecordList **)dst) = G_RECORD_LIST(pygobject_get(arg));
break;
default:
diff --git a/plugins/kaitai/python/records/list.h b/plugins/kaitai/python/records/list.h
new file mode 100644
index 0000000..53572a9
--- /dev/null
+++ b/plugins/kaitai/python/records/list.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/list.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_LIST_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_LIST_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_list_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordList'. */
+bool ensure_python_record_list_is_registered(void);
+
+/* Tente de convertir en correspondance attribut/binaire. */
+int convert_to_record_list(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_LIST_H */
diff --git a/plugins/kaitai/python/records/module.c b/plugins/kaitai/python/records/module.c
new file mode 100644
index 0000000..af97434
--- /dev/null
+++ b/plugins/kaitai/python/records/module.c
@@ -0,0 +1,124 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire records en tant que module
+ *
+ * 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 "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "bits.h"
+#include "delayed.h"
+#include "empty.h"
+#include "group.h"
+#include "item.h"
+#include "list.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.kaitai.records' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_records_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_RECORDS_DOC \
+ "This module is providing objects used to link structure" \
+ " definitions with their data."
+
+ static PyModuleDef py_chrysalide_kaitai_records_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.kaitai.records",
+ .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_RECORDS_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ module = build_python_module(super, &py_chrysalide_kaitai_records_module);
+
+ result = (module != NULL);
+
+ assert(result);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'plugins.kaitai.records'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_kaitai_records_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ 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();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/records/module.h b/plugins/kaitai/python/records/module.h
new file mode 100644
index 0000000..ff631dc
--- /dev/null
+++ b/plugins/kaitai/python/records/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire records en tant que module
+ *
+ * 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_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.records' au module Python. */
+bool add_kaitai_records_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.records'. */
+bool populate_kaitai_records_module(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_MODULE_H */
diff --git a/plugins/kaitai/python/rost/Makefile.am b/plugins/kaitai/python/rost/Makefile.am
new file mode 100644
index 0000000..cae0419
--- /dev/null
+++ b/plugins/kaitai/python/rost/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_LTLIBRARIES = libkaitaipythonrost.la
+
+libkaitaipythonrost_la_SOURCES = \
+ module.h module.c \
+ trigger.h trigger.c
+
+libkaitaipythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonrost_la_SOURCES:%c=)
diff --git a/plugins/kaitai/python/rost/module.c b/plugins/kaitai/python/rost/module.c
new file mode 100644
index 0000000..66a5a82
--- /dev/null
+++ b/plugins/kaitai/python/rost/module.c
@@ -0,0 +1,115 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire rost en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "trigger.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.kaitai.rost' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_rost_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC \
+ "This module creates some glue to extend the ROST features" \
+ " using Kaitai definitions for analyzing and filtering" \
+ " contents."
+
+ static PyModuleDef py_chrysalide_kaitai_rost_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.kaitai.rost",
+ .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ module = build_python_module(super, &py_chrysalide_kaitai_rost_module);
+
+ result = (module != NULL);
+
+ assert(result);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'plugins.kaitai.rost'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_kaitai_rost_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_kaitai_trigger_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/rost/module.h b/plugins/kaitai/python/rost/module.h
new file mode 100644
index 0000000..8415c2e
--- /dev/null
+++ b/plugins/kaitai/python/rost/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire rost en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.rost' au module Python. */
+bool add_kaitai_rost_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.rost'. */
+bool populate_kaitai_rost_module(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H */
diff --git a/plugins/kaitai/python/rost/trigger.c b/plugins/kaitai/python/rost/trigger.c
new file mode 100644
index 0000000..180ef6e
--- /dev/null
+++ b/plugins/kaitai/python/rost/trigger.c
@@ -0,0 +1,236 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.c - équivalent Python du fichier "plugins/kaitai/rost/trigger.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "trigger.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/scan/item.h>
+
+
+#include "../parsers/struct.h"
+#include "../../parsers/struct.h"
+#include "../../rost/trigger-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_trigger, G_TYPE_KAITAI_TRIGGER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_trigger_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_trigger_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GKaitaiStruct *kstruct; /* Définition Kaitai en place */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiTrigger *trigger; /* Création GLib à transmettre */
+
+#define KAITAI_TRIGGER_DOC \
+ "The KaitaiTrigger object store an access to a loaded Kaitai definition" \
+ " creates as many as required instances from it when ROST filters contents" \
+ " with the help of the Kaitai module.\n" \
+ "\n" \
+ "Instances can be created using following constructor:\n" \
+ "\n" \
+ " KaitaiTrigger(kstruct)" \
+ "\n" \
+ "Where *kstruct* is a pychrysalide.plugins.kaitai.parsers.KaitaiStruct" \
+ " instance loaded with a valid Kaitai definition."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_structure, &kstruct);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ trigger = G_KAITAI_TRIGGER(pygobject_get(self));
+
+ if (!g_kaitai_trigger_create(trigger, kstruct))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+ return -1;
+
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_trigger_type(void)
+{
+ static PyMethodDef py_kaitai_trigger_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_trigger_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_trigger_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.rost.KaitaiTrigger",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_TRIGGER_DOC,
+
+ .tp_methods = py_kaitai_trigger_methods,
+ .tp_getset = py_kaitai_trigger_getseters,
+
+ .tp_init = py_kaitai_trigger_init,
+ .tp_new = py_kaitai_trigger_new,
+
+ };
+
+ return &py_kaitai_trigger_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....rost.KaitaiTrigger. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_trigger_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordEmpty' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_trigger_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.rost");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_registered_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TRIGGER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en accès à une définition Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_trigger(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_trigger_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai trigger");
+ break;
+
+ case 1:
+ *((GKaitaiTrigger **)dst) = G_KAITAI_TRIGGER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/rost/trigger.h b/plugins/kaitai/python/rost/trigger.h
new file mode 100644
index 0000000..44776f7
--- /dev/null
+++ b/plugins/kaitai/python/rost/trigger.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/rost/trigger.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H
+#define _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_trigger_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.rost.KaitaiTrigger'. */
+bool ensure_python_kaitai_trigger_is_registered(void);
+
+/* Tente de convertir en accès à une définition Kaitai. */
+int convert_to_kaitai_trigger(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H */
diff --git a/plugins/kaitai/python/scope.c b/plugins/kaitai/python/scope.c
new file mode 100644
index 0000000..b11dc81
--- /dev/null
+++ b/plugins/kaitai/python/scope.c
@@ -0,0 +1,542 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.c - équivalent Python du fichier "plugins/kaitai/scope.c"
+ *
+ * Copyright (C) 2020 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 "scope.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "record.h"
+#include "parsers/meta.h"
+#include "../record.h"
+#include "../parsers/meta.h"
+
+
+
+/* Rassemblement de données d'un paquet */
+typedef struct _py_kaitai_scope_t
+{
+ PyObject_HEAD /* A laisser en premier */
+
+ kaitai_scope_t *native; /* Tampon de données lié */
+
+} py_kaitai_scope_t;
+
+
+/* Libère de la mémoire un objet Python 'py_kaitai_scope_t'. */
+static void py_kaitai_scope_dealloc(py_kaitai_scope_t *);
+
+/* Initialise un objet Python de type 'py_kaitai_scope_t'. */
+static int py_kaitai_scope_init(py_kaitai_scope_t *, PyObject *, PyObject *);
+
+/* Conserve le souvenir de la dernière correspondance effectuée. */
+static PyObject *py_kaitai_scope_remember_last_record(PyObject *, PyObject *);
+
+/* Recherche la définition d'un type nouveau pour Kaitai. */
+static PyObject *py_kaitai_scope_find_sub_type(PyObject *, PyObject *);
+
+/* Retourne le souvenir d'une correspondance racine. */
+static PyObject *py_kaitai_scope_get_root_record(PyObject *, void *);
+
+/* Retourne le souvenir de la correspondance parente effectuée. */
+static PyObject *py_kaitai_scope_get_parent_record(PyObject *, void *);
+
+/* Retourne le souvenir de la dernière correspondance effectuée. */
+static PyObject *py_kaitai_scope_get_last_record(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = tampon de données à supprimer. *
+* *
+* Description : Libère de la mémoire un objet Python 'py_kaitai_scope_t'. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_kaitai_scope_dealloc(py_kaitai_scope_t *self)
+{
+ reset_record_scope(self->native);
+
+ Py_TYPE(self)->tp_free((PyObject *)self);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = instance d'objet à initialiser. *
+* args = arguments passés pour l'appel. *
+* kwds = mots clefs éventuellement fournis en complément. *
+* *
+* Description : Initialise un objet Python de type 'py_kaitai_scope_t'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_scope_init(py_kaitai_scope_t *self, PyObject *args, PyObject *kwds)
+{
+ int result; /* Bilan à retourner */
+ GKaitaiMeta *meta; /* Informations globale */
+ int ret; /* Bilan de lecture des args. */
+
+#define KAITAI_SCOPE_DOC \
+ "The KaitaiScope object stores a local environment which freezes" \
+ " a particular state of the Kaitai parser. It allows the dynamic" \
+ " resolving of values contained in a Kaitai expression.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KaitaiScope(meta)" \
+ "\n" \
+ "Where *meta* is a pychrysalide.plugins.kaitai.parsers.KaitaiMeta" \
+ " instance pointing to global information about the Kaitai" \
+ " definition."
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_meta, &meta);
+ if (!ret) return -1;
+
+ self->native = malloc(sizeof(kaitai_scope_t));
+
+ init_record_scope(self->native, meta);
+
+ result = 0;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = environnement local à manipuler. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Conserve le souvenir de la dernière correspondance effectuée.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_remember_last_record(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ GMatchRecord *record; /* Correspondance à utiliser */
+ int ret; /* Bilan de lecture des args. */
+ py_kaitai_scope_t *locals; /* Instance à manipuler */
+
+#define KAITAI_SCOPE_REMEMBER_LAST_RECORD_METHOD PYTHON_METHOD_DEF \
+( \
+ remember_last_record, "$self, record, /", \
+ METH_VARARGS, py_kaitai_scope, \
+ "Store a record as the last parsed record.\n" \
+ "\n" \
+ "This *record* is expected to be a" \
+ " pychrysalide.plugins.kaitai.MatchRecord instance." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_match_record, &record);
+ if (!ret) return NULL;
+
+ locals = (py_kaitai_scope_t *)self;
+
+ remember_last_record(locals->native, record);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = environnement local à manipuler. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Recherche la définition d'un type nouveau pour Kaitai. *
+* *
+* Retour : Type prêt à emploi ou NULL si non trouvé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_find_sub_type(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ const char *name; /* Désignation à retrouver */
+ int ret; /* Bilan de lecture des args. */
+ py_kaitai_scope_t *locals; /* Instance à manipuler */
+ GKaitaiType *type; /* Définition à identifier */
+
+#define KAITAI_SCOPE_FIND_SUB_TYPE_METHOD PYTHON_METHOD_DEF \
+( \
+ find_sub_type, "$self, name, /", \
+ METH_VARARGS, py_kaitai_scope, \
+ "Retrieve the type structure linked to a given name.\n" \
+ "\n" \
+ "This *name* has to be a string.\n" \
+ "\n" \
+ "The result is a known" \
+ " pychrysalide.plugins.kaitai.parsers.KaitaiType instance" \
+ " or *None* if the name has not been registered during" \
+ " the parsing." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &name);
+ if (!ret) return NULL;
+
+ locals = (py_kaitai_scope_t *)self;
+
+ type = find_sub_type(locals->native, name);
+
+ result = pygobject_new(G_OBJECT(type));
+ g_object_unref(G_OBJECT(type));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = environnement local à consulter. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Retourne le souvenir d'une correspondance racine. *
+* *
+* Retour : Dernière correspondance établie ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_get_root_record(PyObject *self, void *closure)
+{
+ PyObject *result; /* Conversion à retourner */
+ py_kaitai_scope_t *locals; /* Instance à manipuler */
+ GMatchRecord *record; /* Correspondance à convertir */
+
+#define KAITAI_SCOPE_ROOT_RECORD_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ root_record, py_kaitai_scope, \
+ "Provide the first record for a parsed content.\n" \
+ "\n" \
+ "The result is a pychrysalide.plugins.kaitai.MatchRecord" \
+ " instance or *None*." \
+)
+
+ locals = (py_kaitai_scope_t *)self;
+
+ record = get_root_record(locals->native);
+
+ if (record != NULL)
+ {
+ result = pygobject_new(G_OBJECT(record));
+ g_object_unref(G_OBJECT(record));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = environnement local à consulter. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Retourne le souvenir de la correspondance parente effectuée. *
+* *
+* Retour : Dernière correspondance établie ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_get_parent_record(PyObject *self, void *closure)
+{
+ PyObject *result; /* Conversion à retourner */
+ py_kaitai_scope_t *locals; /* Instance à manipuler */
+ GMatchRecord *record; /* Correspondance à convertir */
+
+#define KAITAI_SCOPE_PARENT_RECORD_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ parent_record, py_kaitai_scope, \
+ "Provide the current parent record for a parsed content.\n" \
+ "\n" \
+ "The result is a pychrysalide.plugins.kaitai.MatchRecord" \
+ " instance or *None*." \
+)
+
+ locals = (py_kaitai_scope_t *)self;
+
+ record = get_parent_record(locals->native);
+
+ if (record != NULL)
+ {
+ result = pygobject_new(G_OBJECT(record));
+ g_object_unref(G_OBJECT(record));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = environnement local à consulter. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Retourne le souvenir de la dernière correspondance effectuée.*
+* *
+* Retour : Dernière correspondance établie ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_get_last_record(PyObject *self, void *closure)
+{
+ PyObject *result; /* Conversion à retourner */
+ py_kaitai_scope_t *locals; /* Instance à manipuler */
+ GMatchRecord *record; /* Correspondance à convertir */
+
+#define KAITAI_SCOPE_LAST_RECORD_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ last_record, py_kaitai_scope, \
+ "Provide the last createdrecord for a parsed content.\n" \
+ "\n" \
+ "The result is a pychrysalide.plugins.kaitai.MatchRecord" \
+ " instance or *None*." \
+)
+
+ locals = (py_kaitai_scope_t *)self;
+
+ record = get_last_record(locals->native);
+
+ if (record != NULL)
+ {
+ result = pygobject_new(G_OBJECT(record));
+ g_object_unref(G_OBJECT(record));
+ }
+ 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_kaitai_scope_type(void)
+{
+ static PyMethodDef py_kaitai_scope_methods[] = {
+ KAITAI_SCOPE_REMEMBER_LAST_RECORD_METHOD,
+ KAITAI_SCOPE_FIND_SUB_TYPE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_scope_getseters[] = {
+ KAITAI_SCOPE_ROOT_RECORD_ATTRIB,
+ KAITAI_SCOPE_PARENT_RECORD_ATTRIB,
+ KAITAI_SCOPE_LAST_RECORD_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_scope_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.KaitaiScope",
+ .tp_basicsize = sizeof(py_kaitai_scope_t),
+
+ .tp_dealloc = (destructor)py_kaitai_scope_dealloc,
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = KAITAI_SCOPE_DOC,
+
+ .tp_methods = py_kaitai_scope_methods,
+ .tp_getset = py_kaitai_scope_getseters,
+
+ .tp_init = (initproc)py_kaitai_scope_init,
+ .tp_new = PyType_GenericNew,
+
+ };
+
+ return &py_kaitai_scope_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.common.PackedBuffer'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_scope_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'PackedBuffer' */
+ PyObject *module; /* Module à recompléter */
+
+ type = get_python_kaitai_scope_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ if (PyType_Ready(type) != 0)
+ return false;
+
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ if (!register_python_module_object(module, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = structure interne à copier en objet Python. *
+* *
+* Description : Convertit une structure 'kaitai_scope_t' en objet Python. *
+* *
+* Retour : Object Python résultant de la conversion opérée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *build_from_internal_kaitai_scope(const kaitai_scope_t *locals)
+{
+ PyObject *result; /* Instance à retourner */
+ PyTypeObject *type; /* Type à instancier */
+
+ type = get_python_kaitai_scope_type();
+
+ result = PyObject_CallObject((PyObject *)type, NULL);
+
+ copy_record_scope(((py_kaitai_scope_t *)result)->native, locals);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 environnement local pour Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_scope(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_scope_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai scope");
+ break;
+
+ case 1:
+ *((kaitai_scope_t **)dst) = ((py_kaitai_scope_t *)arg)->native;
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/scope.h b/plugins/kaitai/python/scope.h
new file mode 100644
index 0000000..9353b06
--- /dev/null
+++ b/plugins/kaitai/python/scope.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/scope.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_SCOPE_H
+#define _PLUGINS_KAITAI_PYTHON_SCOPE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+#include "../scope.h"
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_scope_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.common.PackedBuffer'. */
+bool ensure_python_kaitai_scope_is_registered(void);
+
+/* Convertit une structure 'kaitai_scope_t' en objet Python. */
+PyObject *build_from_internal_kaitai_scope(const kaitai_scope_t *);
+
+/* Tente de convertir en environnement local pour Kaitai. */
+int convert_to_kaitai_scope(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_SCOPE_H */
diff --git a/plugins/kaitai/python/stream.c b/plugins/kaitai/python/stream.c
new file mode 100644
index 0000000..985e3c3
--- /dev/null
+++ b/plugins/kaitai/python/stream.c
@@ -0,0 +1,278 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.h - équivalent Python du fichier "plugins/kaitai/stream.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "stream.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 "../stream-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_stream, G_TYPE_KAITAI_STREAM);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_stream_init(PyObject *, PyObject *, PyObject *);
+
+/* Détermine si la fin des données a été atteinte. */
+static PyObject *py_kaitai_stream_get_eof(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_kaitai_stream_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GBinContent *content; /* Contenu binaire manipulé */
+ vmpa2t *pos; /* Tête de lecture courante */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiStream *stream; /* Création GLib à transmettre */
+
+#define KAITAI_STREAM_DOC \
+ "KaitaiStream collects all the information useful for the processing of" \
+ " binary data." \
+ "\n" \
+ "Instances can be created using following constructor:\n" \
+ "\n" \
+ " KaitaiStream(content, pos)" \
+ "\n" \
+ "Where *content* is a pychrysalide.analysis.BinContent instance providing" \
+ " the processed data and *pos* defines the current reading location, as a" \
+ " pychrysalide.arch.vmpa value."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &content, convert_any_to_vmpa, &pos);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ stream = G_KAITAI_STREAM(pygobject_get(self));
+
+ if (!g_kaitai_stream_create(stream, content, pos))
+ {
+ clean_vmpa_arg(pos);
+
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+ return -1;
+
+ }
+
+ clean_vmpa_arg(pos);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Détermine si la fin des données a été atteinte. *
+* *
+* Retour : True si la tête de lecture est en position finale, ou False. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_stream_get_eof(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiStream *stream; /* Version native dyu flux */
+ bool status; /* Etat de la position courante*/
+
+#define KAITAI_STREAM_EOF_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ eof, py_kaitai_stream, \
+ "Boolean value stating if the end of the stream" \
+ " has been reached or not." \
+)
+
+ stream = G_KAITAI_STREAM(pygobject_get(self));
+
+ status = g_kaitai_stream_has_reached_eof(stream);
+
+ result = status ? Py_True : Py_False;
+ 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_kaitai_stream_type(void)
+{
+ static PyMethodDef py_kaitai_stream_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_stream_getseters[] = {
+ KAITAI_STREAM_EOF_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_stream_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.KaitaiStream",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_STREAM_DOC,
+
+ .tp_methods = py_kaitai_stream_methods,
+ .tp_getset = py_kaitai_stream_getseters,
+
+ .tp_init = py_kaitai_stream_init,
+ .tp_new = py_kaitai_stream_new,
+
+ };
+
+ return &py_kaitai_stream_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiStream.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_stream_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'KaitaiStream' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_stream_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_STREAM, 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 flux de données pour Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_stream(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_stream_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai stream");
+ break;
+
+ case 1:
+ *((GKaitaiStream **)dst) = G_KAITAI_STREAM(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/stream.h b/plugins/kaitai/python/stream.h
new file mode 100644
index 0000000..4f61358
--- /dev/null
+++ b/plugins/kaitai/python/stream.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/stream.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_STREAM_H
+#define _PLUGINS_KAITAI_PYTHON_STREAM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_stream_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.KaitaiStream'. */
+bool ensure_python_kaitai_stream_is_registered(void);
+
+/* Tente de convertir en flux de données pour Kaitai. */
+int convert_to_kaitai_stream(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_STREAM_H */
diff --git a/plugins/kaitai/record-int.h b/plugins/kaitai/record-int.h
new file mode 100644
index 0000000..5ce5b2c
--- /dev/null
+++ b/plugins/kaitai/record-int.h
@@ -0,0 +1,73 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record-int.h - prototypes internes pour la mémorisation d'une correspondance avec un attribut Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_RECORD_INT_H
+#define PLUGINS_KAITAI_RECORD_INT_H
+
+
+#include "record.h"
+
+
+#include "parser.h"
+
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+typedef void (* get_record_range_fc) (const GMatchRecord *, mrange_t *);
+
+/* Recherche la correspondance associée à un identifiant. */
+typedef GMatchRecord * (* find_record_by_name_fc) (GMatchRecord *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+typedef bool (* resolve_record_enum_fc) (const GMatchRecord *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+/* Correspondance entre un attribut et du binaire (instance) */
+struct _GMatchRecord
+{
+ GObject parent; /* A laisser en premier */
+
+ GKaitaiParser *creator; /* Lecteur à l'origine */
+
+ GBinContent *content; /* Contenu binaire analysé */
+
+};
+
+/* Correspondance entre un attribut et du binaire (classe) */
+struct _GMatchRecordClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ get_record_range_fc get_range; /* Fourniture de couverture */
+ find_record_by_name_fc find; /* Recherche selon identifiant */
+ resolve_record_enum_fc resolve; /* Conversion d'une énumération*/
+
+};
+
+
+/* Met en place une correspondance entre attribut et binaire. */
+bool g_match_record_create(GMatchRecord *, GKaitaiParser *, GBinContent *);
+
+
+
+#endif /* PLUGINS_KAITAI_RECORD_INT_H */
diff --git a/plugins/kaitai/record.c b/plugins/kaitai/record.c
new file mode 100644
index 0000000..de1e80d
--- /dev/null
+++ b/plugins/kaitai/record.c
@@ -0,0 +1,416 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record.c - définition d'une correspondance avec un attribut Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "record.h"
+
+
+#include <assert.h>
+
+
+#include "expression.h"
+#include "record-int.h"
+#include "parsers/attribute.h"
+
+
+
+/* Initialise la classe des correspondances avec du binaire. */
+static void g_match_record_class_init(GMatchRecordClass *);
+
+/* Initialise une correspondance avec du binaire. */
+static void g_match_record_init(GMatchRecord *);
+
+/* Supprime toutes les références externes. */
+static void g_match_record_dispose(GMatchRecord *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_match_record_finalize(GMatchRecord *);
+
+/* Recherche la correspondance associée à un identifiant. */
+static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *, const char *, size_t, unsigned int);
+
+
+
+/* Indique le type défini pour une correspondance avec du binaire. */
+G_DEFINE_TYPE(GMatchRecord, g_match_record, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des correspondances avec du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_record_class_init(GMatchRecordClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_match_record_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_match_record_finalize;
+
+ klass->find = (find_record_by_name_fc)_g_match_record_find_by_name;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = instance à initialiser. *
+* *
+* Description : Initialise une correspondance avec du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_record_init(GMatchRecord *record)
+{
+ record->creator = NULL;
+
+ record->content = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_record_finalize(GMatchRecord *record)
+{
+ G_OBJECT_CLASS(g_match_record_parent_class)->finalize(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à initialiser pleinement. *
+* creator = lecteur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* *
+* Description : Met en place une correspondance entre attribut et binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_match_record_create(GMatchRecord *record, GKaitaiParser *creator, GBinContent *content)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ record->creator = creator;
+ g_object_ref(G_OBJECT(creator));
+
+ record->content = content;
+
+ if (content != NULL)
+ g_object_ref(G_OBJECT(content));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à consulter. *
+* *
+* Description : Renvoie vers le lecteur à l'origine de la correspondance. *
+* *
+* Retour : Lecteur à l'origine de la création. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiParser *g_match_record_get_creator(const GMatchRecord *record)
+{
+ GKaitaiParser *result; /* Instance à retourner */
+
+ result = record->creator;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à modifier. *
+* creator = lecteur à l'origine de la correspondance. *
+* *
+* Description : Modifie la référence au créateur de la correspondance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_match_record_fix_creator(GMatchRecord *record, GKaitaiParser *creator)
+{
+ g_object_unref(G_OBJECT(record->creator));
+
+ record->creator = creator;
+ g_object_ref(G_OBJECT(creator));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à consulter. *
+* *
+* Description : Fournit le contenu lié à une correspondance établie. *
+* *
+* Retour : Contenu binaire associé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *g_match_record_get_content(const GMatchRecord *record)
+{
+ GBinContent *result; /* Instance à retourner */
+
+ result = record->content;
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
+
+void g_match_record_get_range(const GMatchRecord *record, mrange_t *range)
+{
+ GMatchRecordClass *class; /* Classe de l'instance */
+
+ class = G_MATCH_RECORD_GET_CLASS(record);
+
+ class->get_range(record, range);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance établie à consulter. *
+* out = tableau d'octets retournés. [OUT] *
+* len = taille de ce tableau alloué. [OUT] *
+* *
+* Description : Lit les octets bruts couverts par une correspondance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_match_record_read_raw_bytes(const GMatchRecord *record, bin_t **out, size_t *len)
+{
+ mrange_t range; /* Zone de correspondance */
+ const bin_t *data; /* Accès aux données brutes */
+
+ g_match_record_get_range(record, &range);
+
+ *len = get_mrange_length(&range);
+
+ data = g_binary_content_get_raw_access(record->content, get_mrange_addr(&range), *len);
+ assert(data != NULL);
+
+ *out = malloc(sizeof(bin_t) * (*len + 1));
+
+ memcpy(*out, data, *len);
+ (*out)[*len] = '\0';
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à consulter. *
+* name = désignation de l'élément recherché. *
+* len = taille de cette désignation. *
+* level = profondeur maximale à atteindre (fond : 0). *
+* *
+* Description : Recherche la correspondance associée à un identifiant. *
+* *
+* Retour : Correspondance trouvée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *record, const char *name, size_t len, unsigned int level)
+{
+ GMatchRecord *result; /* Trouvaille à retourner */
+ const char *label; /* Etiquette à manipuler */
+ size_t label_len; /* Taille de cette étiquette */
+
+ result = NULL;
+
+ if (G_IS_KAITAI_ATTRIBUTE(record->creator))
+ {
+ label = g_kaitai_attribute_get_label(G_KAITAI_ATTRIBUTE(record->creator));
+
+ if (label != NULL)
+ {
+ label_len = strlen(label);
+
+ if (label_len == len && strncmp(label, name, len) == 0)
+ {
+ result = record;
+ g_object_ref(G_OBJECT(result));
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à consulter. *
+* name = désignation de l'élément recherché. *
+* len = taille de cette désignation. *
+* level = profondeur maximale à atteindre (fond : 0). *
+* *
+* Description : Recherche la correspondance associée à un identifiant. *
+* *
+* Retour : Correspondance trouvée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *g_match_record_find_by_name(GMatchRecord *record, const char *name, size_t len, unsigned int level)
+{
+ GMatchRecord *result; /* Trouvaille à retourner */
+ GMatchRecordClass *class; /* Classe de l'instance */
+
+ class = G_MATCH_RECORD_GET_CLASS(record);
+
+ result = class->find(record, name, len, level);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à consulter. *
+* name = désignation de l'élément recherché. *
+* label = étiquette de l'élément constant à traduire. *
+* value = valeur entière correspondante. [OUT] *
+* *
+* Description : Transforme une énumération en constante entière. *
+* *
+* Retour : Bilan de l'opération : true si la résolution est réalisée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_match_record_resolve_enum(const GMatchRecord *record, const sized_string_t *name, const sized_string_t *label, resolved_value_t *value)
+{
+ bool result; /* Bilan à retourner */
+ GMatchRecordClass *class; /* Classe de l'instance */
+
+ class = G_MATCH_RECORD_GET_CLASS(record);
+
+ if (class->resolve == NULL)
+ result = false;
+
+ else
+ result = class->resolve(record, name, label, value);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/record.h b/plugins/kaitai/record.h
new file mode 100644
index 0000000..7db8187
--- /dev/null
+++ b/plugins/kaitai/record.h
@@ -0,0 +1,88 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record.h - prototypes pour la définition d'une correspondance avec un attribut Kaitai
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORD_H
+#define _PLUGINS_KAITAI_RECORD_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/content.h>
+#include <arch/vmpa.h>
+#include <common/szstr.h>
+
+
+
+/* Depuis parser.h : spécification d'un lecteur Kaitai (instance) */
+typedef struct _GKaitaiParser GKaitaiParser;
+
+/* Depuis expression.h : informations transportées par une expression */
+typedef struct _resolved_value_t resolved_value_t;
+
+
+
+#define G_TYPE_MATCH_RECORD g_match_record_get_type()
+#define G_MATCH_RECORD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MATCH_RECORD, GMatchRecord))
+#define G_IS_MATCH_RECORD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MATCH_RECORD))
+#define G_MATCH_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MATCH_RECORD, GMatchRecordClass))
+#define G_IS_MATCH_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MATCH_RECORD))
+#define G_MATCH_RECORD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_MATCH_RECORD, GMatchRecordClass))
+
+
+/* Correspondance entre un attribut et du binaire (instance) */
+typedef struct _GMatchRecord GMatchRecord;
+
+/* Correspondance entre un attribut et du binaire (classe) */
+typedef struct _GMatchRecordClass GMatchRecordClass;
+
+
+/* Indique le type défini pour une correspondance avec du binaire. */
+GType g_match_record_get_type(void);
+
+/* Renvoie vers le lecteur à l'origine de la correspondance. */
+GKaitaiParser *g_match_record_get_creator(const GMatchRecord *);
+
+/* Modifie la référence au créateur de la correspondance. */
+void g_match_record_fix_creator(GMatchRecord *, GKaitaiParser *);
+
+/* Fournit le contenu lié à une correspondance établie. */
+GBinContent *g_match_record_get_content(const GMatchRecord *);
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+void g_match_record_get_range(const GMatchRecord *, mrange_t *);
+
+/* Lit les octets bruts couverts par une correspondance. */
+void g_match_record_read_raw_bytes(const GMatchRecord *, bin_t **, size_t *);
+
+#define DIRECT_SEARCH_DEEP_LEVEL 1
+
+/* Recherche la correspondance associée à un identifiant. */
+GMatchRecord *g_match_record_find_by_name(GMatchRecord *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+bool g_match_record_resolve_enum(const GMatchRecord *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORD_H */
diff --git a/plugins/kaitai/records/Makefile.am b/plugins/kaitai/records/Makefile.am
new file mode 100644
index 0000000..3884bfb
--- /dev/null
+++ b/plugins/kaitai/records/Makefile.am
@@ -0,0 +1,23 @@
+
+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 \
+ group.h group.c \
+ item-int.h \
+ item.h item.c \
+ list-int.h \
+ list.h list.c
+
+libkaitairecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitairecords_la_SOURCES:%c=)
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/delayed-int.h b/plugins/kaitai/records/delayed-int.h
new file mode 100644
index 0000000..9275500
--- /dev/null
+++ b/plugins/kaitai/records/delayed-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed-int.h - prototypes internes pour la conservation d'une instance virtuelle
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H
+#define _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H
+
+
+#include "delayed.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Valeur calculée selon des correspondances parallèles (instance) */
+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 _GRecordDelayedClass
+{
+ GMatchRecordClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une valeur calculée selon des correspondances. */
+bool g_record_delayed_create(GRecordDelayed *, GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H */
diff --git a/plugins/kaitai/records/delayed.c b/plugins/kaitai/records/delayed.c
new file mode 100644
index 0000000..8c1395c
--- /dev/null
+++ b/plugins/kaitai/records/delayed.c
@@ -0,0 +1,352 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.c - conservation d'une correspondance entre attribut et binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "delayed.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "delayed-int.h"
+#include "item.h"
+#include "../parsers/attribute.h"
+
+
+
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
+
+
+/* Initialise la classe des valeurs purement calculées. */
+static void g_record_delayed_class_init(GRecordDelayedClass *);
+
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_delayed_init(GRecordDelayed *);
+
+/* Supprime toutes les références externes. */
+static void g_record_delayed_dispose(GRecordDelayed *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_delayed_finalize(GRecordDelayed *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_delayed_get_range(const GRecordDelayed *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UNE CORRESPONDANCE UNITAIRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
+G_DEFINE_TYPE(GRecordDelayed, g_record_delayed, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des valeurs purement calculées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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_delayed_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_delayed_finalize;
+
+ record = G_MATCH_RECORD_CLASS(klass);
+
+ record->get_range = (get_record_range_fc)g_record_delayed_get_range;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : delayed = instance à initialiser. *
+* *
+* Description : Initialise une correspondance entre attribut et binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_delayed_init(GRecordDelayed *delayed)
+{
+ init_record_scope(&delayed->locals, NULL);
+
+ delayed->real_record = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : delayed = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_delayed_dispose(GRecordDelayed *delayed)
+{
+ reset_record_scope(&delayed->locals);
+
+ G_OBJECT_CLASS(g_record_delayed_parent_class)->dispose(G_OBJECT(delayed));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : delayed = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_delayed_finalize(GRecordDelayed *delayed)
+{
+ 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. *
+* content = contenu binaire lié à la correspondance. *
+* *
+* Description : Crée une nouvelle valeur calculée à partir d'une instance. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRecordDelayed *g_record_delayed_new(GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
+{
+ GRecordDelayed *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_RECORD_DELAYED, NULL);
+
+ if (!g_record_delayed_create(result, inst, locals, content))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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(delayed), G_KAITAI_PARSER(inst), content);
+
+ if (result)
+ copy_record_scope(&delayed->locals, locals);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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é. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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(delayed));
+ assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+ 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));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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é. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *delayed, resolved_value_t *out)
+{
+ bool result; /* Bilan à retourner */
+ sized_string_t converted; /* Conversion finale ? */
+
+ result = g_record_delayed_compute_value(delayed, out);
+
+ if (result)
+ {
+ /**
+ * Lorsque c'est possible, les tableaux Kaitai sont transformés en série
+ * d'octets.
+ *
+ * Même si les tableaux ont une grande portée en interne des règles
+ * Kaitai (par exemple pour constituer une table de constantes de
+ * référence), il en est différemment à l'extérieur du processus de
+ * traitement : les tableaux sont le plus souvent destinés à manipuler
+ * les octets représentés directement (par exemple :
+ * "contents: [0xca, 0xfe, 0xba, 0xbe]").
+ *
+ * Pour les valeurs d'instance dont le type n'est pas explicite,
+ * le choix est fait de tenter de simplifier la vie de l'utilisateur
+ * en lui fournissant directement les octets qu'il attend probablement
+ * plutôt qu'un tableau contenant des octets à extraire.
+ */
+
+ if (out->type == GVT_ARRAY)
+ {
+ if (g_kaitai_array_convert_to_bytes(out->array, &converted))
+ {
+ EXIT_RESOLVED_VALUE(*out);
+
+ out->bytes = converted;
+ out->type = GVT_BYTES;
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : delayed = 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_delayed_get_range(const GRecordDelayed *delayed, mrange_t *range)
+{
+ copy_mrange(range, UNUSED_MRANGE_PTR);
+
+}
diff --git a/plugins/kaitai/records/delayed.h b/plugins/kaitai/records/delayed.h
new file mode 100644
index 0000000..e88bb6c
--- /dev/null
+++ b/plugins/kaitai/records/delayed.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.h - prototypes pour la conservation d'une correspondance entre attribut et binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_H
+#define _PLUGINS_KAITAI_RECORDS_DELAYED_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/instance.h"
+
+
+
+#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 _GRecordDelayed GRecordDelayed;
+
+/* Valeur calculée selon des correspondances parallèles (classe) */
+typedef struct _GRecordDelayedClass GRecordDelayedClass;
+
+
+/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
+GType g_record_delayed_get_type(void);
+
+/* Crée une nouvelle valeur calculée à partir d'une instance. */
+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_delayed_compute_value(GRecordDelayed *, resolved_value_t *);
+
+/* Détermine et ajuste la valeur d'un élément Kaitai calculé. */
+bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *, resolved_value_t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_H */
diff --git a/plugins/kaitai/records/empty-int.h b/plugins/kaitai/records/empty-int.h
new file mode 100644
index 0000000..2c6cefa
--- /dev/null
+++ b/plugins/kaitai/records/empty-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty-int.h - prototypes internes pour la notification d'une absence de correspondance attendue
+ *
+ * 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_EMPTY_INT_H
+#define _PLUGINS_KAITAI_RECORDS_EMPTY_INT_H
+
+
+#include "empty.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Marque d'une zone de correspondance vide (instance) */
+struct _GRecordEmpty
+{
+ GMatchRecord parent; /* A laisser en premier */
+
+ vmpa2t pos; /* Début d'une zone vide */
+
+};
+
+/* Marque d'une zone de correspondance vide (classe) */
+struct _GRecordEmptyClass
+{
+ GMatchRecordClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une zone de correspondance vide. */
+bool g_record_empty_create(GRecordEmpty *, GKaitaiParser *, GBinContent *, const vmpa2t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_EMPTY_INT_H */
diff --git a/plugins/kaitai/records/empty.c b/plugins/kaitai/records/empty.c
new file mode 100644
index 0000000..e5121e1
--- /dev/null
+++ b/plugins/kaitai/records/empty.c
@@ -0,0 +1,236 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.c - conservation d'une correspondance entre attribut et binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "empty.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "empty-int.h"
+
+
+
+/* ------------------ DEFINITION D'UNE ZONE DE CORRESPONDANCE VIDE ------------------ */
+
+
+/* Initialise la classe des zones de correspondance vides. */
+static void g_record_empty_class_init(GRecordEmptyClass *);
+
+/* Initialise une zone de correspondance vide. */
+static void g_record_empty_init(GRecordEmpty *);
+
+/* Supprime toutes les références externes. */
+static void g_record_empty_dispose(GRecordEmpty *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_empty_finalize(GRecordEmpty *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_empty_get_range(const GRecordEmpty *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UNE ZONE DE CORRESPONDANCE VIDE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une zone de correspondance vide. */
+G_DEFINE_TYPE(GRecordEmpty, g_record_empty, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des zones de correspondance vides. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_empty_class_init(GRecordEmptyClass *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_empty_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_empty_finalize;
+
+ record = G_MATCH_RECORD_CLASS(klass);
+
+ record->get_range = (get_record_range_fc)g_record_empty_get_range;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : empty = instance à initialiser. *
+* *
+* Description : Initialise une zone de correspondance vide. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_empty_init(GRecordEmpty *empty)
+{
+ init_vmpa(&empty->pos, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : empty = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_empty_dispose(GRecordEmpty *empty)
+{
+ G_OBJECT_CLASS(g_record_empty_parent_class)->dispose(G_OBJECT(empty));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : empty = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_empty_finalize(GRecordEmpty *empty)
+{
+ G_OBJECT_CLASS(g_record_empty_parent_class)->finalize(G_OBJECT(empty));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : parser = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* pos = emplacement de la zone vide à construire. *
+* *
+* Description : Crée une zone de correspondance vide à une position donnée. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRecordEmpty *g_record_empty_new(GKaitaiParser *parser, GBinContent *content, const vmpa2t *pos)
+{
+ GRecordEmpty *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_RECORD_EMPTY, NULL);
+
+ if (!g_record_empty_create(result, parser, content, pos))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : empty = correspondance à initialiser pleinement. *
+* parser = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* pos = emplacement de la zone vide à construire. *
+* *
+* Description : Met en place une zone de correspondance vide. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_record_empty_create(GRecordEmpty *empty, GKaitaiParser *parser, GBinContent *content, const vmpa2t *pos)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_match_record_create(G_MATCH_RECORD(empty), parser, content);
+
+ if (result)
+ copy_vmpa(&empty->pos, pos);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : empty = 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_empty_get_range(const GRecordEmpty *empty, mrange_t *range)
+{
+ init_mrange(range, &empty->pos, 0);
+
+}
diff --git a/plugins/kaitai/records/empty.h b/plugins/kaitai/records/empty.h
new file mode 100644
index 0000000..4e89b62
--- /dev/null
+++ b/plugins/kaitai/records/empty.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.h - prototypes pour la notification d'une absence de correspondance attendue
+ *
+ * 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_EMPTY_H
+#define _PLUGINS_KAITAI_RECORDS_EMPTY_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+
+
+
+#define G_TYPE_RECORD_EMPTY g_record_empty_get_type()
+#define G_RECORD_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_EMPTY, GRecordEmpty))
+#define G_IS_RECORD_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_EMPTY))
+#define G_RECORD_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_EMPTY, GRecordEmptyClass))
+#define G_IS_RECORD_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_EMPTY))
+#define G_RECORD_EMPTY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_EMPTY, GRecordEmptyClass))
+
+
+/* Marque d'une zone de correspondance vide (instance) */
+typedef struct _GRecordEmpty GRecordEmpty;
+
+/* Marque d'une zone de correspondance vide (classe) */
+typedef struct _GRecordEmptyClass GRecordEmptyClass;
+
+
+/* Indique le type défini pour une zone de correspondance vide. */
+GType g_record_empty_get_type(void);
+
+/* Crée une zone de correspondance vide à une position donnée. */
+GRecordEmpty *g_record_empty_new(GKaitaiParser *, GBinContent *, const vmpa2t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_EMPTY_H */
diff --git a/plugins/kaitai/records/group-int.h b/plugins/kaitai/records/group-int.h
new file mode 100644
index 0000000..1fd0162
--- /dev/null
+++ b/plugins/kaitai/records/group-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group-int.h - prototypes internes pour la conservation d'un groupe de correspondance avec du 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_GROUP_INT_H
+#define _PLUGINS_KAITAI_RECORDS_GROUP_INT_H
+
+
+#include "group.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Groupe de correspondances établies entre attributs et binaire (instance) */
+struct _GRecordGroup
+{
+ GMatchRecord parent; /* A laisser en premier */
+
+ GMatchRecord **children; /* Sous-correspondances */
+ size_t count; /* Taille de cette série */
+
+};
+
+/* Groupe de correspondances établies entre attributs et binaire (classe) */
+struct _GRecordGroupClass
+{
+ GMatchRecordClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une série de correspondances attribut/binaire. */
+bool g_record_group_create(GRecordGroup *, GKaitaiStruct *, GBinContent *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_GROUP_INT_H */
diff --git a/plugins/kaitai/records/group.c b/plugins/kaitai/records/group.c
new file mode 100644
index 0000000..13327c8
--- /dev/null
+++ b/plugins/kaitai/records/group.c
@@ -0,0 +1,382 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.c - conservation d'un groupe de correspondance avec du 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 "group.h"
+
+
+#include <malloc.h>
+
+
+#include "group-int.h"
+#include "../parsers/attribute.h"
+
+
+
+/* ------------------ DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES ------------------ */
+
+
+/* Initialise la classe des groupes de correspondances. */
+static void g_record_group_class_init(GRecordGroupClass *);
+
+/* Initialise une série de correspondances attributs/binaire. */
+static void g_record_group_init(GRecordGroup *);
+
+/* Supprime toutes les références externes. */
+static void g_record_group_dispose(GRecordGroup *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_group_finalize(GRecordGroup *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_group_get_range(const GRecordGroup *, mrange_t *);
+
+/* Recherche la correspondance associée à un identifiant. */
+static GMatchRecord *g_record_group_find_by_name(GRecordGroup *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+static bool g_record_group_resolve_enum(const GRecordGroup *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+G_DEFINE_TYPE(GRecordGroup, g_record_group, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des groupes de correspondances. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_group_class_init(GRecordGroupClass *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_group_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_group_finalize;
+
+ record = G_MATCH_RECORD_CLASS(klass);
+
+ record->get_range = (get_record_range_fc)g_record_group_get_range;
+ record->find = (find_record_by_name_fc)g_record_group_find_by_name;
+ record->resolve = (resolve_record_enum_fc)g_record_group_resolve_enum;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = instance à initialiser. *
+* *
+* Description : Initialise une série de correspondances attributs/binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_group_init(GRecordGroup *group)
+{
+ group->children = NULL;
+ group->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_group_dispose(GRecordGroup *group)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < group->count; i++)
+ g_clear_object(&group->children[i]);
+
+ G_OBJECT_CLASS(g_record_group_parent_class)->dispose(G_OBJECT(group));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_group_finalize(GRecordGroup *group)
+{
+ if (group->children != NULL)
+ free(group->children);
+
+ G_OBJECT_CLASS(g_record_group_parent_class)->finalize(G_OBJECT(group));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire lié à la correspondance. *
+* kstruct = analyseur à l'origine de la correspondance. *
+* *
+* Description : Crée une nouvelle série de correspondances attribut/binaire. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRecordGroup *g_record_group_new(GKaitaiStruct *kstruct, GBinContent *content)
+{
+ GRecordGroup *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_RECORD_GROUP, NULL);
+
+ if (!g_record_group_create(result, kstruct, content))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = correspondance à initialiser pleinement. *
+* kstruct = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* *
+* Description : Met en place une série de correspondances attribut/binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_record_group_create(GRecordGroup *group, GKaitaiStruct *kstruct, GBinContent *content)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_match_record_create(G_MATCH_RECORD(group), G_KAITAI_PARSER(kstruct), content);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = ensemble de correspondances attribut/binaire. *
+* record = sous-corresponde à intégrer. *
+* *
+* Description : Ajoute une correspondance supplémentaire à une série. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_record_group_add_record(GRecordGroup *group, GMatchRecord *record)
+{
+ group->children = realloc(group->children, ++group->count * sizeof(GMatchRecord));
+
+ group->children[group->count - 1] = record;
+ g_object_ref(G_OBJECT(record));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : group = 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_group_get_range(const GRecordGroup *group, mrange_t *range)
+{
+ vmpa2t start; /* Position de départ */
+ mrange_t range_0; /* Première zone couverte */
+ mrange_t range_n; /* Dernière zone couverte */
+ vmpa2t end; /* Position de d'arrivée */
+ phys_t length; /* Taille de zone couverte */
+
+ if (group->count == 0)
+ {
+ init_vmpa(&start, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+ init_mrange(range, &start, VMPA_NO_PHYSICAL);
+ }
+
+ else
+ {
+ g_match_record_get_range(group->children[0], &range_0);
+ g_match_record_get_range(group->children[group->count - 1], &range_n);
+
+ copy_vmpa(&start, get_mrange_addr(&range_0));
+
+ compute_mrange_end_addr(&range_n, &end);
+ length = compute_vmpa_diff(&start, &end);
+
+ init_mrange(range, &start, length);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = ensemble de correspondances attribut/binaire. *
+* name = désignation de l'élément recherché. *
+* len = taille de cette désignation. *
+* level = profondeur maximale à atteindre (fond : 0). *
+* *
+* Description : Recherche la correspondance associée à un identifiant. *
+* *
+* Retour : Correspondance trouvée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GMatchRecord *g_record_group_find_by_name(GRecordGroup *group, const char *name, size_t len, unsigned int level)
+{
+ GMatchRecord *result; /* Correspondance à renvoyer */
+ GMatchRecordClass *class; /* Classe parente normalisée */
+ size_t i; /* Boucle de parcours */
+
+ class = G_MATCH_RECORD_CLASS(g_record_group_parent_class);
+
+ /**
+ * Le cas d'un type utilisateur peut rattacher un attribut Kaitai à un groupe...
+ */
+ result = class->find(G_MATCH_RECORD(group), name, len, level);
+
+ if (level > 0)
+ {
+ level--;
+
+ for (i = 0; i < group->count && result == NULL; i++)
+ result = g_match_record_find_by_name(group->children[i], name, len, level);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : group = ensemble de correspondances attribut/binaire. *
+* name = désignation de l'élément recherché. *
+* label = étiquette de l'élément constant à traduire. *
+* value = valeur entière correspondante. [OUT] *
+* *
+* Description : Transforme une énumération en constante entière. *
+* *
+* Retour : Bilan de l'opération : true si la résolution est réalisée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_record_group_resolve_enum(const GRecordGroup *group, const sized_string_t *name, const sized_string_t *label, resolved_value_t *value)
+{
+ bool result; /* Bilan à retourner */
+ GMatchRecord *base; /* Autre version du groupe */
+ size_t i; /* Boucle de parcours */
+ GKaitaiEnum *kenum; /* Enumération à consulter */
+
+ result = false;
+
+ base = G_MATCH_RECORD(group);
+
+ if (G_IS_KAITAI_STRUCT(base->creator))
+ {
+ kenum = g_kaitai_structure_get_enum(G_KAITAI_STRUCT(base->creator), name);
+
+ if (kenum != NULL)
+ {
+ result = g_kaitai_enum_find_value(kenum, label, value);
+ g_object_unref(G_OBJECT(kenum));
+ }
+
+ }
+
+ for (i = 0; i < group->count && !result; i++)
+ result = g_match_record_resolve_enum(group->children[i], name, label, value);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/records/group.h b/plugins/kaitai/records/group.h
new file mode 100644
index 0000000..454dade
--- /dev/null
+++ b/plugins/kaitai/records/group.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.h - prototypes pour la conservation d'un groupe de correspondance avec du 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_GROUP_H
+#define _PLUGINS_KAITAI_RECORDS_GROUP_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/content.h>
+
+
+#include "../record.h"
+#include "../parsers/struct.h"
+
+
+
+#define G_TYPE_RECORD_GROUP g_record_group_get_type()
+#define G_RECORD_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_GROUP, GRecordGroup))
+#define G_IS_RECORD_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_GROUP))
+#define G_RECORD_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_GROUP, GRecordGroupClass))
+#define G_IS_RECORD_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_GROUP))
+#define G_RECORD_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_GROUP, GRecordGroupClass))
+
+
+/* Groupe de correspondances établies entre attributs et binaire (instance) */
+typedef struct _GRecordGroup GRecordGroup;
+
+/* Groupe de correspondances établies entre attributs et binaire (classe) */
+typedef struct _GRecordGroupClass GRecordGroupClass;
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+GType g_record_group_get_type(void);
+
+/* Crée une nouvelle série de correspondances attribut/binaire. */
+GRecordGroup *g_record_group_new(GKaitaiStruct *, GBinContent *);
+
+/* Ajoute une correspondance supplémentaire à une série. */
+void g_record_group_add_record(GRecordGroup *, GMatchRecord *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_GROUP_H */
diff --git a/plugins/kaitai/records/item-int.h b/plugins/kaitai/records/item-int.h
new file mode 100644
index 0000000..56e0a41
--- /dev/null
+++ b/plugins/kaitai/records/item-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item-int.h - prototypes internes pour la conservation d'une correspondance entre attribut et binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_ITEM_INT_H
+#define _PLUGINS_KAITAI_RECORDS_ITEM_INT_H
+
+
+#include "item.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Correspondance établie entre un attribut et du binaire (instance) */
+struct _GRecordItem
+{
+ GMatchRecord parent; /* A laisser en premier */
+
+ mrange_t range; /* Zone de binaire couverte */
+ SourceEndian endian; /* Boutisme des données imposé */
+
+};
+
+/* Correspondance établie entre un attribut et du binaire (classe) */
+struct _GRecordItemClass
+{
+ GMatchRecordClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une correspondance entre attribut et binaire. */
+bool g_record_item_create(GRecordItem *, GKaitaiAttribute *, GBinContent *, const mrange_t *, SourceEndian);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_ITEM_INT_H */
diff --git a/plugins/yaml/scalar.c b/plugins/kaitai/records/item.c
index 1dd5989..0bcf9f7 100644
--- a/plugins/yaml/scalar.c
+++ b/plugins/kaitai/records/item.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * scalar.c - noeud Yaml de type "scalar"
+ * item.c - conservation d'une correspondance entre attribut et binaire
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -21,61 +21,56 @@
*/
-#include "scalar.h"
+#include "item.h"
-#include <malloc.h>
+#include <assert.h>
#include <string.h>
-#include "node-int.h"
+#include "item-int.h"
-/* Noeud d'une arborescence au format Yaml (instance) */
-struct _GYamlScalar
-{
- GYamlNode parent; /* A laisser en premier */
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
- GYamlLine *key; /* Clef principale du noeud */
- GYamlCollection *collection; /* Collection de noeuds */
-};
+/* Initialise la classe des correspondances attribut/binaire. */
+static void g_record_item_class_init(GRecordItemClass *);
-/* Noeud d'une arborescence au format Yaml (classe) */
-struct _GYamlScalarClass
-{
- GYamlNodeClass parent; /* A laisser en premier */
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_item_init(GRecordItem *);
+
+/* Supprime toutes les références externes. */
+static void g_record_item_dispose(GRecordItem *);
-};
+/* Procède à la libération totale de la mémoire. */
+static void g_record_item_finalize(GRecordItem *);
-/* Initialise la classe des noeuds d'arborescence Yaml. */
-static void g_yaml_scalar_class_init(GYamlScalarClass *);
-/* Initialise une instance de noeud d'arborescence Yaml. */
-static void g_yaml_scalar_init(GYamlScalar *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Supprime toutes les références externes. */
-static void g_yaml_scalar_dispose(GYamlScalar *);
-/* Procède à la libération totale de la mémoire. */
-static void g_yaml_scalar_finalize(GYamlScalar *);
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_item_get_range(const GRecordItem *, mrange_t *);
+
-/* Recherche les noeuds correspondant à un chemin. */
-static void g_yaml_scalar_find_by_path(const GYamlScalar *, const char *, bool, GYamlNode ***, size_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UNE CORRESPONDANCE UNITAIRE */
+/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour un noeud d'arborescence Yaml. */
-G_DEFINE_TYPE(GYamlScalar, g_yaml_scalar, G_TYPE_YAML_NODE);
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+G_DEFINE_TYPE(GRecordItem, g_record_item, G_TYPE_MATCH_RECORD);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des noeuds d'arborescence Yaml. *
+* Description : Initialise la classe des correspondances attribut/binaire. *
* *
* Retour : - *
* *
@@ -83,28 +78,28 @@ G_DEFINE_TYPE(GYamlScalar, g_yaml_scalar, G_TYPE_YAML_NODE);
* *
******************************************************************************/
-static void g_yaml_scalar_class_init(GYamlScalarClass *klass)
+static void g_record_item_class_init(GRecordItemClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GYamlNodeClass *node; /* Version parente de classe */
+ GMatchRecordClass *record; /* Version parente de la classe*/
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_yaml_scalar_dispose;
- object->finalize = (GObjectFinalizeFunc)g_yaml_scalar_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_record_item_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_item_finalize;
- node = G_YAML_NODE_CLASS(klass);
+ record = G_MATCH_RECORD_CLASS(klass);
- node->find = (find_yaml_node_fc)g_yaml_scalar_find_by_path;
+ record->get_range = (get_record_range_fc)g_record_item_get_range;
}
/******************************************************************************
* *
-* Paramètres : node = instance à initialiser. *
+* Paramètres : item = instance à initialiser. *
* *
-* Description : Initialise une instance de noeud d'arborescence Yaml. *
+* Description : Initialise une correspondance entre attribut et binaire. *
* *
* Retour : - *
* *
@@ -112,17 +107,16 @@ static void g_yaml_scalar_class_init(GYamlScalarClass *klass)
* *
******************************************************************************/
-static void g_yaml_scalar_init(GYamlScalar *node)
+static void g_record_item_init(GRecordItem *item)
{
- node->key = NULL;
- node->collection = NULL;
+ copy_mrange(&item->range, UNUSED_MRANGE_PTR);
}
/******************************************************************************
* *
-* Paramètres : node = instance d'objet GLib à traiter. *
+* Paramètres : item = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -132,20 +126,16 @@ static void g_yaml_scalar_init(GYamlScalar *node)
* *
******************************************************************************/
-static void g_yaml_scalar_dispose(GYamlScalar *node)
+static void g_record_item_dispose(GRecordItem *item)
{
- g_clear_object(&node->key);
-
- g_clear_object(&node->collection);
-
- G_OBJECT_CLASS(g_yaml_scalar_parent_class)->dispose(G_OBJECT(node));
+ G_OBJECT_CLASS(g_record_item_parent_class)->dispose(G_OBJECT(item));
}
/******************************************************************************
* *
-* Paramètres : node = instance d'objet GLib à traiter. *
+* Paramètres : item = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -155,18 +145,21 @@ static void g_yaml_scalar_dispose(GYamlScalar *node)
* *
******************************************************************************/
-static void g_yaml_scalar_finalize(GYamlScalar *node)
+static void g_record_item_finalize(GRecordItem *item)
{
- G_OBJECT_CLASS(g_yaml_scalar_parent_class)->finalize(G_OBJECT(node));
+ G_OBJECT_CLASS(g_record_item_parent_class)->finalize(G_OBJECT(item));
}
/******************************************************************************
* *
-* Paramètres : key = line Yaml représentant la clef du futur noeud. *
+* Paramètres : attrib = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* range = zone couverture par la correspondance. *
+* endian = boustime des données à respecter. *
* *
-* Description : Construit un noeud d'arborescence Yaml. *
+* Description : Crée une nouvelle correspondance entre attribut et binaire. *
* *
* Retour : Instance mise en place ou NULL en cas d'échec. *
* *
@@ -174,24 +167,14 @@ static void g_yaml_scalar_finalize(GYamlScalar *node)
* *
******************************************************************************/
-GYamlScalar *g_yaml_scalar_new(GYamlLine *key)
+GRecordItem *g_record_item_new(GKaitaiAttribute *attrib, GBinContent *content, const mrange_t *range, SourceEndian endian)
{
- GYamlScalar *result; /* Structure à retourner */
+ GRecordItem *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_YAML_SCALAR, NULL);
+ result = g_object_new(G_TYPE_RECORD_ITEM, NULL);
- /**
- * Le paragraphe "3.2.2.1. Keys Order" des spécifications précise
- * qu'une séquence n'est qu'un noeud sans correspondance clef/valeur.
- *
- * Cette situation doit donc être prise en compte.
- */
-
- if (key != NULL)
- {
- result->key = key;
- g_object_ref(G_OBJECT(key));
- }
+ if (!g_record_item_create(result, attrib, content, range, endian))
+ g_clear_object(&result);
return result;
@@ -200,24 +183,33 @@ GYamlScalar *g_yaml_scalar_new(GYamlLine *key)
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
+* Paramètres : item = correspondance à initialiser pleinement. *
+* attrib = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* range = zone couverte par la correspondance. *
+* endian = boustime des données à respecter. *
* *
-* Description : Fournit la ligne principale associée à un noeud. *
+* Description : Met en place une correspondance entre attribut et binaire. *
* *
-* Retour : Ligne Yaml à l'origine du noeud. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlLine *g_yaml_scalar_get_yaml_line(const GYamlScalar *node)
+bool g_record_item_create(GRecordItem *item, GKaitaiAttribute *attrib, GBinContent *content, const mrange_t *range, SourceEndian endian)
{
- GYamlLine *result; /* Ligne d'origine à renvoyer */
+ bool result; /* Bilan à retourner */
+
+ result = g_match_record_create(G_MATCH_RECORD(item), G_KAITAI_PARSER(attrib), content);
+
+ if (result)
+ {
+ copy_mrange(&item->range, range);
- result = node->key;
+ item->endian = endian;
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
+ }
return result;
@@ -226,62 +218,83 @@ GYamlLine *g_yaml_scalar_get_yaml_line(const GYamlScalar *node)
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à compléter. *
-* collec = collection de noeuds Yaml. *
+* Paramètres : item = correspondance à consulter. *
+* out = tableau d'octets retournés. [OUT] *
+* len = taille de ce tableau alloué. [OUT] *
* *
-* Description : Attache une collection de noeuds Yaml à un noeud. *
+* Description : Lit la série d'octets d'un élément Kaitai entier représenté. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_yaml_scalar_set_collection(GYamlScalar *node, GYamlCollection *collec)
+bool g_record_item_get_truncated_bytes(const GRecordItem *item, bin_t **out, size_t *len)
{
- g_clear_object(&node->collection);
+ bool result; /* Bilan à retourner */
+ GKaitaiParser *parser; /* Attribut associé à l'élément*/
+
+ parser = g_match_record_get_creator(G_MATCH_RECORD(item));
+ assert(G_IS_KAITAI_ATTRIBUTE(parser));
- g_object_ref_sink(G_OBJECT(collec));
- node->collection = collec;
+ result = g_kaitai_attribute_read_truncated_bytes(G_KAITAI_ATTRIBUTE(parser),
+ G_MATCH_RECORD(item)->content,
+ &item->range,
+ out, len);
+
+ g_object_unref(G_OBJECT(parser));
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
+* Paramètres : item = correspondance à consulter. *
+* out = valeur à sauvegarder sous une forme générique. [OUT] *
* *
-* Description : Fournit une éventuelle collection rattachée à un noeud. *
+* Description : Lit la valeur d'un élément Kaitai entier représenté. *
* *
-* Retour : Collection de noeuds Yaml ou NULL. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlCollection *g_yaml_scalar_get_collection(const GYamlScalar *node)
+bool g_record_item_get_value(const GRecordItem *item, resolved_value_t *out)
{
- GYamlCollection *result; /* Collection à renvoyer */
+ bool result; /* Bilan à retourner */
+ GKaitaiParser *parser; /* Attribut associé à l'élément*/
+
+ parser = g_match_record_get_creator(G_MATCH_RECORD(item));
+ assert(G_IS_KAITAI_ATTRIBUTE(parser));
- result = node->collection;
+ result = g_kaitai_attribute_read_value(G_KAITAI_ATTRIBUTE(parser),
+ G_MATCH_RECORD(item)->content,
+ &item->range,
+ item->endian, out);
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
+ g_object_unref(G_OBJECT(parser));
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* nodes = liste de noeuds avec correspondance établie. [OUT] *
-* count = quantité de ces noeuds. [OUT] *
+* Paramètres : item = correspondance à consulter. *
+* range = zone de couverture déterminée. [OUT] *
* *
-* Description : Recherche les noeuds correspondant à un chemin. *
+* Description : Calcule ou fournit la zone couverte par une correspondance. *
* *
* Retour : - *
* *
@@ -289,90 +302,8 @@ GYamlCollection *g_yaml_scalar_get_collection(const GYamlScalar *node)
* *
******************************************************************************/
-static void g_yaml_scalar_find_by_path(const GYamlScalar *node, const char *path, bool prepare, GYamlNode ***nodes, size_t *count)
+static void g_record_item_get_range(const GRecordItem *item, mrange_t *range)
{
- GYamlLine *line; /* Ligne Yaml liée au noeud */
- const char *key; /* Clef associée au noeud */
- char *next; /* Prochaine partie du chemin */
- size_t cmplen; /* Etendue de la comparaison */
- int ret; /* Bilan d'une comparaison */
- GYamlCollection *collec; /* Collection de noeuds */
-
- if (path[0] == '\0')
- goto exit;
-
- line = g_yaml_scalar_get_yaml_line(node);
-
- /* Correspondance au niveau du noeud ? */
-
- if (line != NULL)
- {
- if (path[0] == '/')
- {
- path++;
-
- if (path[0] == '\0')
- goto matched;
-
- }
-
- key = g_yaml_line_get_key(line);
-
- next = strchr(path, '/');
-
- if (next == NULL)
- ret = strcmp(path, key);
-
- else
- {
- cmplen = next - path;
-
- if (cmplen == 0)
- goto cont;
-
- ret = strncmp(path, key, cmplen);
-
- }
-
- if (ret != 0)
- goto done;
-
- else if (next != NULL)
- {
- path += cmplen;
- goto cont;
- }
-
- matched:
-
- *nodes = realloc(*nodes, ++(*count) * sizeof(GYamlNode **));
-
- g_object_ref(G_OBJECT(node));
- (*nodes)[*count - 1] = G_YAML_NODE(node);
-
- goto done;
-
- }
-
- cont:
-
- collec = g_yaml_scalar_get_collection(node);
-
- if (collec != NULL)
- {
- _g_yaml_node_find_by_path(G_YAML_NODE(collec), path, prepare, nodes, count);
-
- g_object_unref(G_OBJECT(collec));
-
- }
-
- done:
-
- if (line != NULL)
- g_object_unref(G_OBJECT(line));
-
- exit:
-
- ;
+ copy_mrange(range, &item->range);
}
diff --git a/plugins/kaitai/records/item.h b/plugins/kaitai/records/item.h
new file mode 100644
index 0000000..1286a89
--- /dev/null
+++ b/plugins/kaitai/records/item.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour la conservation d'une correspondance entre attribut et binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_ITEM_H
+#define _PLUGINS_KAITAI_RECORDS_ITEM_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+
+
+
+#define G_TYPE_RECORD_ITEM g_record_item_get_type()
+#define G_RECORD_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_ITEM, GRecordItem))
+#define G_IS_RECORD_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_ITEM))
+#define G_RECORD_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_ITEM, GRecordItemClass))
+#define G_IS_RECORD_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_ITEM))
+#define G_RECORD_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_ITEM, GRecordItemClass))
+
+
+/* Correspondance établie entre un attribut et du binaire (instance) */
+typedef struct _GRecordItem GRecordItem;
+
+/* Correspondance établie entre un attribut et du binaire (classe) */
+typedef struct _GRecordItemClass GRecordItemClass;
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+GType g_record_item_get_type(void);
+
+/* Crée une nouvelle correspondance entre attribut et binaire. */
+GRecordItem *g_record_item_new(GKaitaiAttribute *, GBinContent *, const mrange_t *, SourceEndian);
+
+/* Lit la série d'octets d'un élément Kaitai entier représenté. */
+bool g_record_item_get_truncated_bytes(const GRecordItem *, bin_t **, size_t *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+bool g_record_item_get_value(const GRecordItem *, resolved_value_t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_ITEM_H */
diff --git a/plugins/kaitai/records/list-int.h b/plugins/kaitai/records/list-int.h
new file mode 100644
index 0000000..88b411d
--- /dev/null
+++ b/plugins/kaitai/records/list-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list-int.h - prototypes internes pour la conservation d'une liste de correspondance avec du binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_LIST_INT_H
+#define _PLUGINS_KAITAI_RECORDS_LIST_INT_H
+
+
+#include "list.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Liste de correspondances établies entre attributs et binaire (instance) */
+struct _GRecordList
+{
+ GMatchRecord parent; /* A laisser en premier */
+
+ vmpa2t pos; /* Début de zone */
+
+ GMatchRecord **children; /* Sous-correspondances */
+ size_t count; /* Taille de cette série */
+
+};
+
+/* Liste de correspondances établies entre attributs et binaire (classe) */
+struct _GRecordListClass
+{
+ GMatchRecordClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une série de correspondances attribut/binaire. */
+bool g_record_list_create(GRecordList *, GKaitaiAttribute *, GBinContent *, const vmpa2t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_LIST_INT_H */
diff --git a/plugins/kaitai/records/list.c b/plugins/kaitai/records/list.c
new file mode 100644
index 0000000..1a36bf5
--- /dev/null
+++ b/plugins/kaitai/records/list.c
@@ -0,0 +1,424 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - conservation d'une liste de correspondance avec du binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "list.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "list-int.h"
+
+
+
+/* ------------------ DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES ------------------ */
+
+
+/* Initialise la classe des listes de correspondances. */
+static void g_record_list_class_init(GRecordListClass *);
+
+/* Initialise une série de correspondances attributs/binaire. */
+static void g_record_list_init(GRecordList *);
+
+/* Supprime toutes les références externes. */
+static void g_record_list_dispose(GRecordList *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_list_finalize(GRecordList *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_list_get_range(const GRecordList *, mrange_t *);
+
+/* Recherche la correspondance associée à un identifiant. */
+static GMatchRecord *g_record_list_find_by_name(GRecordList *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+static bool g_record_list_resolve_enum(const GRecordList *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+G_DEFINE_TYPE(GRecordList, g_record_list, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des listes de correspondances. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_list_class_init(GRecordListClass *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_list_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_list_finalize;
+
+ record = G_MATCH_RECORD_CLASS(klass);
+
+ record->get_range = (get_record_range_fc)g_record_list_get_range;
+ record->find = (find_record_by_name_fc)g_record_list_find_by_name;
+ record->resolve = (resolve_record_enum_fc)g_record_list_resolve_enum;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = instance à initialiser. *
+* *
+* Description : Initialise une série de correspondances attributs/binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_list_init(GRecordList *list)
+{
+ list->children = NULL;
+ list->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_list_dispose(GRecordList *list)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < list->count; i++)
+ g_clear_object(&list->children[i]);
+
+ G_OBJECT_CLASS(g_record_list_parent_class)->dispose(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_list_finalize(GRecordList *list)
+{
+ if (list->children != NULL)
+ free(list->children);
+
+ G_OBJECT_CLASS(g_record_list_parent_class)->finalize(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* pos = début de la zone de couverture de la liste. *
+* *
+* Description : Crée une nouvelle série de correspondances attribut/binaire. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRecordList *g_record_list_new(GKaitaiAttribute *attrib, GBinContent *content, const vmpa2t *pos)
+{
+ GRecordList *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_RECORD_LIST, NULL);
+
+ if (!g_record_list_create(result, attrib, content, pos))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = correspondance à initialiser pleinement. *
+* attrib = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* *
+* Description : Met en place une série de correspondances attribut/binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_record_list_create(GRecordList *list, GKaitaiAttribute *attrib, GBinContent *content, const vmpa2t *pos)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_match_record_create(G_MATCH_RECORD(list), G_KAITAI_PARSER(attrib), content);
+
+ if (result)
+ copy_vmpa(&list->pos, pos);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de correspondances attribut/binaire. *
+* *
+* Description : Dénombre le nombre de correspondances enregistrées. *
+* *
+* Retour : Taille de la liste représentée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_record_list_count_records(const GRecordList *list)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = list->count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de correspondances attribut/binaire. *
+* record = sous-corresponde à intégrer. *
+* *
+* Description : Ajoute une correspondance supplémentaire à une série. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_record_list_add_record(GRecordList *list, GMatchRecord *record)
+{
+ list->children = realloc(list->children, ++list->count * sizeof(GMatchRecord));
+
+ list->children[list->count - 1] = record;
+ g_object_ref(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de correspondances attribut/binaire. *
+* index = indice de la correspondance visée. *
+* *
+* Description : Fournit un élément ciblé dans la liste de correspondances. *
+* *
+* Retour : Instance de correspondance particulière, voire NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *g_record_list_get_record(const GRecordList *list, size_t index)
+{
+ GMatchRecord *result; /* Instance à retourner */
+
+ if (index < list->count)
+ {
+ result = list->children[index];
+ g_object_ref(G_OBJECT(result));
+ }
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : list = 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_list_get_range(const GRecordList *list, mrange_t *range)
+{
+ vmpa2t start; /* Position de départ */
+ mrange_t range_0; /* Première zone couverte */
+ mrange_t range_n; /* Dernière zone couverte */
+ vmpa2t end; /* Position de d'arrivée */
+ phys_t length; /* Taille de zone couverte */
+
+ assert(list->count > 0);
+
+ if (list->count == 0)
+ {
+ init_vmpa(&start, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+ init_mrange(range, &start, VMPA_NO_PHYSICAL);
+ }
+
+ else
+ {
+ g_match_record_get_range(list->children[0], &range_0);
+ g_match_record_get_range(list->children[list->count - 1], &range_n);
+
+ copy_vmpa(&start, get_mrange_addr(&range_0));
+
+ compute_mrange_end_addr(&range_n, &end);
+ length = compute_vmpa_diff(&start, &end);
+
+ init_mrange(range, &start, length);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de correspondances attribut/binaire. *
+* name = désignation de l'élément recherché. *
+* len = taille de cette désignation. *
+* level = profondeur maximale à atteindre (fond : 0). *
+* *
+* Description : Recherche la correspondance associée à un identifiant. *
+* *
+* Retour : Correspondance trouvée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GMatchRecord *g_record_list_find_by_name(GRecordList *list, const char *name, size_t len, unsigned int level)
+{
+ GMatchRecord *result; /* Correspondance à renvoyer */
+ GMatchRecordClass *class; /* Classe parente normalisée */
+ size_t i; /* Boucle de parcours */
+
+ class = G_MATCH_RECORD_CLASS(g_record_list_parent_class);
+
+ result = class->find(G_MATCH_RECORD(list), name, len, level);
+
+ if (level > 0)
+ {
+ for (i = 0; i < list->count && result == NULL; i++)
+ result = g_match_record_find_by_name(list->children[i], name, len, level);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de correspondances attribut/binaire. *
+* name = désignation de l'élément recherché. *
+* label = étiquette de l'élément constant à traduire. *
+* value = valeur entière correspondante. [OUT] *
+* *
+* Description : Transforme une énumération en constante entière. *
+* *
+* Retour : Bilan de l'opération : true si la résolution est réalisée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_record_list_resolve_enum(const GRecordList *list, const sized_string_t *name, const sized_string_t *label, resolved_value_t *value)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ /**
+ * Comme les types peuvent être sélectionnés dynamiquement, le parcours
+ * de l'ensemble des sous-noeuds doit être effectué.
+ */
+
+ result = false;
+
+ for (i = 0; i < list->count && !result; i++)
+ result = g_match_record_resolve_enum(list->children[i], name, label, value);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/records/list.h b/plugins/kaitai/records/list.h
new file mode 100644
index 0000000..03e593e
--- /dev/null
+++ b/plugins/kaitai/records/list.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - prototypes pour la conservation d'une liste de correspondance avec du binaire
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_LIST_H
+#define _PLUGINS_KAITAI_RECORDS_LIST_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/content.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+
+
+
+#define G_TYPE_RECORD_LIST g_record_list_get_type()
+#define G_RECORD_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_LIST, GRecordList))
+#define G_IS_RECORD_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_LIST))
+#define G_RECORD_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_LIST, GRecordListClass))
+#define G_IS_RECORD_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_LIST))
+#define G_RECORD_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_LIST, GRecordListClass))
+
+
+/* Liste de correspondances établies entre attributs et binaire (instance) */
+typedef struct _GRecordList GRecordList;
+
+/* Liste de correspondances établies entre attributs et binaire (classe) */
+typedef struct _GRecordListClass GRecordListClass;
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+GType g_record_list_get_type(void);
+
+/* Crée une nouvelle série de correspondances attribut/binaire. */
+GRecordList *g_record_list_new(GKaitaiAttribute *, GBinContent *, const vmpa2t *);
+
+/* Dénombre le nombre de correspondances enregistrées. */
+size_t g_record_list_count_records(const GRecordList *);
+
+/* Ajoute une correspondance supplémentaire à une série. */
+void g_record_list_add_record(GRecordList *, GMatchRecord *);
+
+/* Fournit un élément ciblé dans la liste de correspondances. */
+GMatchRecord *g_record_list_get_record(const GRecordList *, size_t);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_LIST_H */
diff --git a/plugins/kaitai/rost/Makefile.am b/plugins/kaitai/rost/Makefile.am
new file mode 100644
index 0000000..c7ea84a
--- /dev/null
+++ b/plugins/kaitai/rost/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libkaitairost.la
+
+libkaitairost_la_SOURCES = \
+ browser-int.h \
+ browser.h browser.c \
+ core.h core.c \
+ space-int.h \
+ space.h space.c \
+ trigger-int.h \
+ trigger.h trigger.c
+
+libkaitairost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitairost_la_SOURCES:%c=)
diff --git a/plugins/kaitai/rost/browser-int.h b/plugins/kaitai/rost/browser-int.h
new file mode 100644
index 0000000..4b49680
--- /dev/null
+++ b/plugins/kaitai/rost/browser-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser-int.h - prototypes internes pour le parcours des résultats d'analyse Kaitai pour ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_BROWSER_INT_H
+#define PLUGINS_KAITAI_ROST_BROWSER_INT_H
+
+
+#include <analysis/scan/item-int.h>
+
+
+#include "browser.h"
+
+
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */
+struct _GKaitaiBrowser
+{
+ GScanRegisteredItem parent; /* A laisser en premier */
+
+ char *path; /* Chamin vers l'enregistrement*/
+ GMatchRecord *record; /* Correspondance à parcourir */
+
+};
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */
+struct _GKaitaiBrowserClass
+{
+ GScanRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouveau parcours de correspondances Kaitai. */
+bool g_kaitai_browser_create(GKaitaiBrowser *, const char *, GMatchRecord *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_BROWSER_INT_H */
diff --git a/plugins/kaitai/rost/browser.c b/plugins/kaitai/rost/browser.c
new file mode 100644
index 0000000..159915b
--- /dev/null
+++ b/plugins/kaitai/rost/browser.c
@@ -0,0 +1,478 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser.c - accès à des définitions Kaitai depuis ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "browser.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <analysis/scan/exprs/literal.h>
+
+
+#include "browser-int.h"
+#include "../records/bits.h"
+#include "../records/delayed.h"
+#include "../records/item.h"
+#include "../records/list.h"
+
+
+
+/* ---------------------- PARCOURS DE CORRESPONDANCES ETABLIES ---------------------- */
+
+
+/* Initialise la classe des parcours de correspondances Kaitai. */
+static void g_kaitai_browser_class_init(GKaitaiBrowserClass *);
+
+/* Initialise un parcours de correspondances Kaitai. */
+static void g_kaitai_browser_init(GKaitaiBrowser *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_browser_dispose(GKaitaiBrowser *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_browser_finalize(GKaitaiBrowser *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_kaitai_browser_get_name(const GKaitaiBrowser *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_browser_resolve(GKaitaiBrowser *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_kaitai_browser_reduce(GKaitaiBrowser *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue une extraction d'élément à partir d'une série. */
+static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PARCOURS DE CORRESPONDANCES ETABLIES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */
+G_DEFINE_TYPE(GKaitaiBrowser, g_kaitai_browser, G_TYPE_SCAN_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des parcours de correspondances Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_class_init(GKaitaiBrowserClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_browser_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_browser_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_kaitai_browser_get_name;
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_browser_resolve;
+ registered->reduce = (reduce_registered_item_fc)g_kaitai_browser_reduce;
+ registered->extract = (extract_registered_item_at)g_kaitai_browser_extract_at;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance à initialiser. *
+* *
+* Description : Initialise un parcours de correspondances Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_init(GKaitaiBrowser *browser)
+{
+ browser->path = NULL;
+ browser->record = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_dispose(GKaitaiBrowser *browser)
+{
+ g_clear_object(&browser->record);
+
+ G_OBJECT_CLASS(g_kaitai_browser_parent_class)->dispose(G_OBJECT(browser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_finalize(GKaitaiBrowser *browser)
+{
+ if (browser->path != NULL)
+ free(browser->path);
+
+ G_OBJECT_CLASS(g_kaitai_browser_parent_class)->finalize(G_OBJECT(browser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : path = chemin vers l'enregistrement fourni. *
+* record = correspondance racine à considérer. *
+* *
+* Description : Crée un nouveau parcours de correspondances Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiBrowser *g_kaitai_browser_new(const char *path, GMatchRecord *record)
+{
+ GKaitaiBrowser *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_BROWSER, NULL);
+
+ if (!g_kaitai_browser_create(result, path, record))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = encadrement d'un parcours de correspondances. *
+* path = chemin vers l'enregistrement fourni. *
+* record = correspondance racine à considérer. *
+* *
+* Description : Met en place un nouveau parcours de correspondances Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_browser_create(GKaitaiBrowser *browser, const char *path, GMatchRecord *record)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (path != NULL)
+ browser->path = strdup(path);
+
+ browser->record = record;
+ g_object_ref(G_OBJECT(browser->record));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_kaitai_browser_get_name(const GKaitaiBrowser *item)
+{
+ char *result; /* Désignation à retourner */
+ int ret; /* Statut de construction */
+
+ if (item->path == NULL)
+ result = strdup("kaitai://");
+
+ else
+ {
+ ret = asprintf(&result, "kaitai://%s", item->path);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ result = strdup("kaitai://???");
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_browser_resolve(GKaitaiBrowser *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GMatchRecord *found; /* Correspondance trouvée */
+ char *path;
+ int ret; /* Statut de construction */
+
+ found = g_match_record_find_by_name(item->record, target, strlen(target), 1);
+ result = (found != NULL);
+
+ if (result)
+ {
+ ret = asprintf(&path, "%s.%s", item->path, target);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ path = strdup("!?");
+
+ *out = G_SCAN_REGISTERED_ITEM(g_kaitai_browser_new(path, found));
+
+ free(path);
+ g_object_unref(G_OBJECT(found));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Décompte total à considérer */
+ resolved_value_t value; /* Valeur brute à transformer */
+
+ if (G_IS_RECORD_LIST(item->record))
+ {
+ count = g_record_list_count_records(G_RECORD_LIST(item->record));
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 });
+
+ result = true;
+
+ }
+
+ else
+ {
+ if (G_IS_RECORD_BIT_FIELD(item->record))
+ result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(item->record), &value);
+
+ else if (G_IS_RECORD_DELAYED(item->record))
+ result = g_record_delayed_compute_and_aggregate_value(G_RECORD_DELAYED(item->record), &value);
+
+ else if (G_IS_RECORD_ITEM(item->record))
+ result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value);
+
+ else
+ result = false;
+
+ if (result)
+ {
+ switch (value.type)
+ {
+ case GVT_UNSIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &value.unsigned_integer);
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &value.signed_integer);
+ break;
+
+ case GVT_FLOAT:
+ /* TODO */
+ break;
+
+ case GVT_BOOLEAN:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &value.status);
+ break;
+
+ case GVT_BYTES:
+ *out = g_scan_literal_expression_new(LVT_STRING, &value.bytes);
+ break;
+
+ default:
+ break;
+
+ }
+
+ EXIT_RESOLVED_VALUE(value);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* index = indice de l'élément à cibler. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Effectue une extraction d'élément à partir d'une série. *
+* *
+* Retour : Elément de série obtenu ou NULL si erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *item, const GScanExpression *index, GScanContext *ctx, GScanScope *scope)
+{
+ GObject *result; /* Elément récupéré à renvoyer */
+ GScanLiteralExpression *literal; /* Accès direct à l'indice */
+ LiteralValueType vtype; /* Type de valeur portée */
+ unsigned long long at; /* Valeur concrète du point */
+ bool status; /* Bilan d'obtention d'indice */
+ GRecordList *list; /* Accès direct à la liste */
+ size_t count; /* Décompte total à considérer */
+ GMatchRecord *found; /* Correspondance trouvée */
+ char *path;
+ int ret; /* Statut de construction */
+
+ result = NULL;
+
+ /* Validations préliminaires */
+
+ if (!G_IS_RECORD_LIST(item->record)) goto exit;
+ if (!G_IS_SCAN_LITERAL_EXPRESSION(index)) goto exit;
+
+ literal = G_SCAN_LITERAL_EXPRESSION(index);
+
+ vtype = g_scan_literal_expression_get_value_type(literal);
+ if (vtype != LVT_UNSIGNED_INTEGER) goto exit;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(literal, &at);
+ if (!status) goto exit;
+
+ list = G_RECORD_LIST(item->record);
+
+ count = g_record_list_count_records(list);
+ if (at >= count) goto exit;
+
+ /* Récupération de l'élément visé */
+
+ found = g_record_list_get_record(list, at);
+ if (found == NULL) goto exit;
+
+ ret = asprintf(&path, "%s[%llu]", item->path, at);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ path = strdup("!?");
+
+ result = G_OBJECT(g_kaitai_browser_new(path, found));
+
+ free(path);
+ g_object_unref(G_OBJECT(found));
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/browser.h b/plugins/kaitai/rost/browser.h
new file mode 100644
index 0000000..89b9f6f
--- /dev/null
+++ b/plugins/kaitai/rost/browser.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser.h - prototypes pour le parcours des résultats d'analyse Kaitai pour ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_BROWSER_H
+#define PLUGINS_KAITAI_ROST_BROWSER_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+
+
+
+#define G_TYPE_KAITAI_BROWSER g_kaitai_browser_get_type()
+#define G_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowser))
+#define G_IS_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_BROWSER))
+#define G_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass))
+#define G_IS_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_BROWSER))
+#define G_KAITAI_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass))
+
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */
+typedef struct _GKaitaiBrowser GKaitaiBrowser;
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */
+typedef struct _GKaitaiBrowserClass GKaitaiBrowserClass;
+
+
+/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */
+GType g_kaitai_browser_get_type(void);
+
+/* Crée un nouveau parcours de correspondances Kaitai. */
+GKaitaiBrowser *g_kaitai_browser_new(const char *, GMatchRecord *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_BROWSER_H */
diff --git a/plugins/kaitai/rost/core.c b/plugins/kaitai/rost/core.c
new file mode 100644
index 0000000..8271389
--- /dev/null
+++ b/plugins/kaitai/rost/core.c
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - mise à disposition d'un support Kaitai pour ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <core/global.h>
+
+
+#include "space.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre un support de Kaitai pour ROST. *
+* *
+* Retour : Bilan du chargement mené. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_support_to_rost(void)
+{
+ bool result; /* Bilan à retourner */
+ GScanNamespace *root_ns; /* Espace de noms ROST racine */
+ GScanNamespace *kaitai_ns; /* Espace de noms pour Kaitai */
+
+ result = true;
+
+ root_ns = get_rost_root_namespace();
+
+ kaitai_ns = g_kaitai_namespace_new();
+
+ result = g_scan_namespace_register_item(root_ns, G_SCAN_REGISTERED_ITEM(kaitai_ns));
+
+ g_object_unref(G_OBJECT(kaitai_ns));
+
+ g_object_unref(G_OBJECT(root_ns));
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/core.h b/plugins/kaitai/rost/core.h
new file mode 100644
index 0000000..6f810eb
--- /dev/null
+++ b/plugins/kaitai/rost/core.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour la mise à disposition d'un support Kaitai pour ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_CORE_H
+#define _PLUGINS_KAITAI_ROST_CORE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Intègre un support de Kaitai pour ROST. */
+bool add_kaitai_support_to_rost(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_CORE_H */
diff --git a/plugins/kaitai/rost/space-int.h b/plugins/kaitai/rost/space-int.h
new file mode 100644
index 0000000..47ec707
--- /dev/null
+++ b/plugins/kaitai/rost/space-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space-int.h - prototypes internes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_SPACE_INT_H
+#define _PLUGINS_KAITAI_ROST_SPACE_INT_H
+
+
+#include "space.h"
+
+
+#include <analysis/scan/space-int.h>
+
+
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */
+struct _GKaitaiNamespace
+{
+ GScanNamespace parent; /* A laisser en premier */
+
+};
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */
+struct _GKaitaiNamespaceClass
+{
+ GScanNamespaceClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouvel espace de noms pour scan. */
+bool g_kaitai_namespace_create(GKaitaiNamespace *);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_SPACE_INT_H */
diff --git a/plugins/kaitai/rost/space.c b/plugins/kaitai/rost/space.c
new file mode 100644
index 0000000..ee922d2
--- /dev/null
+++ b/plugins/kaitai/rost/space.c
@@ -0,0 +1,254 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - définition d'un espace de noms pour les fonctions de scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "space.h"
+
+
+#include <string.h>
+
+
+#include "trigger.h"
+#include "space-int.h"
+#include "../import.h"
+
+
+
+/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */
+
+
+/* Initialise la classe des espaces de noms dynamiques Kaitai. */
+static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *);
+
+/* Initialise une instance d'espace de noms dynamiques Kaitai. */
+static void g_kaitai_namespace_init(GKaitaiNamespace *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_namespace_dispose(GKaitaiNamespace *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_namespace_finalize(GKaitaiNamespace *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_namespace_resolve(GKaitaiNamespace *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SOCLE POUR LES ESPACES DE NOMS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */
+G_DEFINE_TYPE(GKaitaiNamespace, g_kaitai_namespace, G_TYPE_SCAN_NAMESPACE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des espaces de noms dynamiques Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_namespace_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_namespace_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_namespace_resolve;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance à initialiser. *
+* *
+* Description : Initialise une instance d'espace de noms dynamiques Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_init(GKaitaiNamespace *space)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_dispose(GKaitaiNamespace *space)
+{
+ G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->dispose(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_finalize(GKaitaiNamespace *space)
+{
+ G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->finalize(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un nouvel espace de noms dynamique pour Kaitai. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanNamespace *g_kaitai_namespace_new(void)
+{
+ GScanNamespace *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_NAMESPACE, NULL);
+
+ if (!g_kaitai_namespace_create(G_KAITAI_NAMESPACE(result)))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'espace de noms à initialiser. *
+* name = désignation du futur espace de noms. *
+* *
+* Description : Met en place un nouvel espace de noms pour scan. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_namespace_create(GKaitaiNamespace *space)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_namespace_create(G_SCAN_NAMESPACE(space), "kaitai");
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_namespace_resolve(GKaitaiNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GScanRegisteredItemClass *parent; /* Version de classe parente */
+ GKaitaiStruct *kstruct; /* Lecteur de définition */
+
+ parent = G_SCAN_REGISTERED_ITEM_CLASS(g_kaitai_namespace_parent_class);
+
+ result = parent->resolve(G_SCAN_REGISTERED_ITEM(item), target, ctx, scope, out);
+
+ if (!result)
+ {
+ kstruct = load_kaitai_definition(target, NULL);
+
+ if (kstruct != NULL)
+ {
+ *out = g_kaitai_trigger_new(kstruct);
+ result = true;
+
+ g_object_unref(G_OBJECT(kstruct));
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/space.h b/plugins/kaitai/rost/space.h
new file mode 100644
index 0000000..5dcea5e
--- /dev/null
+++ b/plugins/kaitai/rost/space.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_SPACE_H
+#define _PLUGINS_KAITAI_ROST_SPACE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/scan/space.h>
+
+
+
+#define G_TYPE_KAITAI_NAMESPACE g_kaitai_namespace_get_type()
+#define G_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespace))
+#define G_IS_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_NAMESPACE))
+#define G_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass))
+#define G_IS_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_NAMESPACE))
+#define G_KAITAI_NAMESPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass))
+
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */
+typedef struct _GKaitaiNamespace GKaitaiNamespace;
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */
+typedef struct _GKaitaiNamespaceClass GKaitaiNamespaceClass;
+
+
+/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */
+GType g_kaitai_namespace_get_type(void);
+
+/* Construit un nouvel espace de noms dynamique pour Kaitai. */
+GScanNamespace *g_kaitai_namespace_new(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_SPACE_H */
diff --git a/plugins/kaitai/rost/trigger-int.h b/plugins/kaitai/rost/trigger-int.h
new file mode 100644
index 0000000..6830cd7
--- /dev/null
+++ b/plugins/kaitai/rost/trigger-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger-int.h - prototypes internes pour l'accès à des définitions Kaitai depuis ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_TRIGGER_INT_H
+#define _PLUGINS_KAITAI_ROST_TRIGGER_INT_H
+
+
+#include <analysis/scan/item-int.h>
+
+
+#include "trigger.h"
+
+
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */
+struct _GKaitaiTrigger
+{
+ GScanRegisteredItem parent; /* A laisser en premier */
+
+ char *name; /* Désignation arbitraire */
+
+ GKaitaiStruct *kstruct; /* Définition à décliner */
+
+};
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */
+struct _GKaitaiTriggerClass
+{
+ GScanRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un accès à une définition Kaitai pour ROST. */
+bool g_kaitai_trigger_create(GKaitaiTrigger *, GKaitaiStruct *);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_TRIGGER_INT_H */
diff --git a/plugins/kaitai/rost/trigger.c b/plugins/kaitai/rost/trigger.c
new file mode 100644
index 0000000..6bb6e5d
--- /dev/null
+++ b/plugins/kaitai/rost/trigger.c
@@ -0,0 +1,320 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.c - accès à des définitions Kaitai depuis ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "trigger.h"
+
+
+#include <string.h>
+
+
+#include "browser.h"
+#include "trigger-int.h"
+
+
+
+/* ---------------------- ACCES ET DECLENCHEMENT D'UNE ANALYSE ---------------------- */
+
+
+/* Initialise la classe des accès aux définitions Kaitai. */
+static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *);
+
+/* Initialise un accès à une définition Kaitai. */
+static void g_kaitai_trigger_init(GKaitaiTrigger *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_trigger_dispose(GKaitaiTrigger *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_trigger_finalize(GKaitaiTrigger *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_trigger_resolve(GKaitaiTrigger *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ACCES ET DECLENCHEMENT D'UNE ANALYSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */
+G_DEFINE_TYPE(GKaitaiTrigger, g_kaitai_trigger, G_TYPE_SCAN_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des accès aux définitions Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_trigger_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_trigger_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_kaitai_trigger_get_name;
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_trigger_resolve;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance à initialiser. *
+* *
+* Description : Initialise un accès à une définition Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_init(GKaitaiTrigger *trigger)
+{
+ trigger->name = NULL;
+
+ trigger->kstruct = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_dispose(GKaitaiTrigger *trigger)
+{
+ g_clear_object(&trigger->kstruct);
+
+ G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->dispose(G_OBJECT(trigger));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_finalize(GKaitaiTrigger *trigger)
+{
+ if (trigger->name != NULL)
+ free(trigger->name);
+
+ G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->finalize(G_OBJECT(trigger));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = définition Kaitai à manipuler avec du contenu. *
+* *
+* Description : Crée un nouvel accès à une définition Kaitai à instancier. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *kstruct)
+{
+ GScanRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_TRIGGER, NULL);
+
+ if (!g_kaitai_trigger_create(G_KAITAI_TRIGGER(result), kstruct))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = lien vers une définition Kaitai à instancier. *
+* kstruct = définition Kaitai à manipuler avec du contenu. *
+* *
+* Description : Met en place un accès à une définition Kaitai pour ROST. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_trigger_create(GKaitaiTrigger *trigger, GKaitaiStruct *kstruct)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ trigger->kstruct = kstruct;
+ g_object_ref(G_OBJECT(trigger->kstruct));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *trigger)
+{
+ char *result; /* Désignation à retourner */
+ GKaitaiMeta *meta; /* Eventuelles métadonnées */
+ const char *id; /* Identifiant de définition */
+
+ if (trigger->name != NULL)
+ result = strdup(trigger->name);
+
+ else
+ {
+ result = NULL;
+
+ meta = g_kaitai_structure_get_meta(trigger->kstruct);
+ if (meta == NULL) goto done;
+
+ id = g_kaitai_meta_get_id(meta);
+ if (id == NULL) goto done;
+
+ result = strdup(id);
+
+ g_object_unref(G_OBJECT(meta));
+
+ done:
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_trigger_resolve(GKaitaiTrigger *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GKaitaiBrowser *browser; /* Navigateur pour résultats */
+ GBinContent *content; /* Contenu binaire à analyser */
+ GMatchRecord *record; /* Premier niveau de résultats */
+
+ browser = g_object_get_data(G_OBJECT(item), "kaitai_browser");
+
+ if (browser == NULL)
+ {
+ content = g_scan_context_get_content(ctx);
+
+ record = g_kaitai_structure_parse(item->kstruct, content);
+
+ g_object_unref(G_OBJECT(content));
+
+ if (record != NULL)
+ {
+ browser = g_kaitai_browser_new(NULL, record);
+
+ g_object_set_data_full(G_OBJECT(item), "kaitai_browser", browser, g_object_unref);
+
+ }
+
+ }
+
+ if (browser == NULL)
+ result = false;
+
+ else
+ result = g_scan_registered_item_resolve(G_SCAN_REGISTERED_ITEM(browser), target, ctx, scope, out);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/trigger.h b/plugins/kaitai/rost/trigger.h
new file mode 100644
index 0000000..f55e998
--- /dev/null
+++ b/plugins/kaitai/rost/trigger.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.h - prototypes pour l'accès à des définitions Kaitai depuis ROST
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_TRIGGER_H
+#define PLUGINS_KAITAI_ROST_TRIGGER_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/scan/item.h>
+
+
+#include "../parsers/struct.h"
+
+
+
+#define G_TYPE_KAITAI_TRIGGER g_kaitai_trigger_get_type()
+#define G_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTrigger))
+#define G_IS_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TRIGGER))
+#define G_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass))
+#define G_IS_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TRIGGER))
+#define G_KAITAI_TRIGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass))
+
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */
+typedef struct _GKaitaiTrigger GKaitaiTrigger;
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */
+typedef struct _GKaitaiTriggerClass GKaitaiTriggerClass;
+
+
+/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */
+GType g_kaitai_trigger_get_type(void);
+
+/* Crée un nouvel accès à une définition Kaitai à instancier. */
+GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_TRIGGER_H */
diff --git a/plugins/kaitai/scope.c b/plugins/kaitai/scope.c
new file mode 100644
index 0000000..fad8890
--- /dev/null
+++ b/plugins/kaitai/scope.c
@@ -0,0 +1,257 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.c - recherches d'éléments de lecture
+ *
+ * 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 "scope.h"
+
+
+#include "parsers/struct.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = contexte de variables locales à initialiser. *
+* meta = informations générales à disposition. *
+* *
+* Description : Initialise un contexte pour correspondances Kaitai établies. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void init_record_scope(kaitai_scope_t *locals, GKaitaiMeta *meta)
+{
+ locals->meta = meta;
+
+ if (meta != NULL)
+ g_object_ref(G_OBJECT(meta));
+
+ locals->root = NULL;
+ locals->parent = NULL;
+ locals->last = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = contexte de variables locales à réinitialiser. *
+* *
+* Description : Vide un contexte de correspondances Kaitai établies. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_record_scope(kaitai_scope_t *locals)
+{
+ g_clear_object(&locals->meta);
+
+ g_clear_object(&locals->root);
+ g_clear_object(&locals->parent);
+ g_clear_object(&locals->last);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = contexte de variables locales à initialiser. *
+* src = contexte de variables locales à copier. *
+* *
+* Description : Copie un contexte de correspondances Kaitai établies. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void copy_record_scope(kaitai_scope_t *dest, const kaitai_scope_t *src)
+{
+ reset_record_scope(dest);
+
+#define COPY_SCOPE_ITEM(itm) \
+ dest->itm = src->itm; \
+ if (dest->itm != NULL) \
+ g_object_ref(G_OBJECT(dest->itm));
+
+ COPY_SCOPE_ITEM(meta);
+
+ COPY_SCOPE_ITEM(root);
+ COPY_SCOPE_ITEM(parent);
+ COPY_SCOPE_ITEM(last);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* *
+* Description : Retourne le souvenir d'une correspondance racine. *
+* *
+* Retour : Dernière correspondance établie ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *get_root_record(const kaitai_scope_t *locals)
+{
+ GMatchRecord *result; /* Instance à retourner */
+
+ result = locals->root;
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* *
+* Description : Retourne le souvenir de la correspondance parente effectuée. *
+* *
+* Retour : Dernière correspondance établie ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *get_parent_record(const kaitai_scope_t *locals)
+{
+ GMatchRecord *result; /* Instance à retourner */
+
+ result = locals->parent;
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* record = dernière correspondance établie. *
+* *
+* Description : Conserve le souvenir de la dernière correspondance effectuée.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void remember_last_record(kaitai_scope_t *locals, GMatchRecord *record)
+{
+ g_clear_object(&locals->last);
+
+ locals->last = record;
+
+ if (record != NULL)
+ g_object_ref(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* *
+* Description : Retourne le souvenir de la dernière correspondance effectuée.*
+* *
+* Retour : Dernière correspondance établie ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *get_last_record(const kaitai_scope_t *locals)
+{
+ GMatchRecord *result; /* Instance à retourner */
+
+ result = locals->last;
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : locals = variables locales pour les résolutions de types. *
+* name = désignation du type particulier ciblé. *
+* *
+* Description : Recherche la définition d'un type nouveau pour Kaitai. *
+* *
+* Retour : Type prêt à emploi ou NULL si non trouvé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiType *find_sub_type(const kaitai_scope_t *locals, const char *name)
+{
+ GKaitaiType *result; /* Instance à retourner */
+ size_t i; /* Boucle de parcours */
+ GKaitaiParser *parser; /* Lecteur d'origine */
+
+ GMatchRecord *list[] = { locals->last, locals->parent, locals->root };
+
+ result = NULL;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (list[i] == NULL)
+ continue;
+
+ parser = g_match_record_get_creator(list[i]);
+
+ if (G_IS_KAITAI_STRUCT(parser))
+ result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(parser), name);
+
+ g_object_unref(G_OBJECT(parser));
+
+ if (result != NULL)
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/scope.h b/plugins/kaitai/scope.h
new file mode 100644
index 0000000..5dc52bf
--- /dev/null
+++ b/plugins/kaitai/scope.h
@@ -0,0 +1,72 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.h - prototypes pour les recherches d'éléments de lecture
+ *
+ * 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_SCOPE_H
+#define _PLUGINS_KAITAI_SCOPE_H
+
+
+#include "record.h"
+#include "parsers/meta.h"
+#include "parsers/type.h"
+
+
+
+/* Accès aux différentes variables de contexte */
+typedef struct _kaitai_scope_t
+{
+ GKaitaiMeta *meta; /* Informations globales */
+
+ GMatchRecord *root; /* Variable "_root" */
+ GMatchRecord *parent; /* Variable "_parent" */
+ GMatchRecord *last; /* Variable "_" */
+
+} kaitai_scope_t;
+
+
+/* Initialise un contexte pour correspondances Kaitai établies. */
+void init_record_scope(kaitai_scope_t *, GKaitaiMeta *);
+
+/* Vide un contexte de correspondances Kaitai établies. */
+void reset_record_scope(kaitai_scope_t *);
+
+/* Copie un contexte de correspondances Kaitai établies. */
+void copy_record_scope(kaitai_scope_t *, const kaitai_scope_t *);
+
+/* Retourne le souvenir d'une correspondance racine. */
+GMatchRecord *get_root_record(const kaitai_scope_t *);
+
+/* Retourne le souvenir de la correspondance parente effectuée. */
+GMatchRecord *get_parent_record(const kaitai_scope_t *);
+
+/* Conserve le souvenir de la dernière correspondance effectuée. */
+void remember_last_record(kaitai_scope_t *, GMatchRecord *);
+
+/* Retourne le souvenir de la dernière correspondance effectuée. */
+GMatchRecord *get_last_record(const kaitai_scope_t *);
+
+/* Recherche la définition d'un type nouveau pour Kaitai. */
+GKaitaiType *find_sub_type(const kaitai_scope_t *, const char *);
+
+
+
+#endif /* _PLUGINS_KAITAI_SCOPE_H */
diff --git a/plugins/kaitai/stream-int.h b/plugins/kaitai/stream-int.h
new file mode 100644
index 0000000..50b71df
--- /dev/null
+++ b/plugins/kaitai/stream-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream-int.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_STREAM_INT_H
+#define PLUGINS_KAITAI_STREAM_INT_H
+
+
+#include "stream.h"
+
+
+
+/* Flux de données à disposition d'une analyse Kaitai (instance) */
+struct _GKaitaiStream
+{
+ GObject parent; /* A laisser en premier */
+
+ GBinContent *content; /* Contenu brut manipulé */
+ vmpa2t pos; /* Tête de lecture dans le flux*/
+
+};
+
+/* Flux de données à disposition d'une analyse Kaitai (classe) */
+struct _GKaitaiStreamClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un flux de données pour Kaitai. */
+bool g_kaitai_stream_create(GKaitaiStream *, GBinContent *, const vmpa2t *);
+
+
+
+#endif /* PLUGINS_KAITAI_STREAM_INT_H */
diff --git a/plugins/kaitai/stream.c b/plugins/kaitai/stream.c
new file mode 100644
index 0000000..66d0f8e
--- /dev/null
+++ b/plugins/kaitai/stream.c
@@ -0,0 +1,237 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.c - données associées à un flux de données Kaitai
+ *
+ * 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 "stream.h"
+
+
+#include "stream-int.h"
+
+
+
+/* Initialise la classe des flux de données pour Kaitai. */
+static void g_kaitai_stream_class_init(GKaitaiStreamClass *);
+
+/* Initialise un flux de données accessibles à Kaitai. */
+static void g_kaitai_stream_init(GKaitaiStream *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_stream_dispose(GKaitaiStream *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_stream_finalize(GKaitaiStream *);
+
+
+
+/* Indique le type défini pour un flux de données manipulé par une lecture Kaitai. */
+G_DEFINE_TYPE(GKaitaiStream, g_kaitai_stream, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des flux de données pour Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_stream_class_init(GKaitaiStreamClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_stream_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_stream_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stream = instance à initialiser. *
+* *
+* Description : Initialise un flux de données accessibles à Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_stream_init(GKaitaiStream *stream)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stream = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_stream_dispose(GKaitaiStream *stream)
+{
+ G_OBJECT_CLASS(g_kaitai_stream_parent_class)->dispose(G_OBJECT(stream));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stream = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_stream_finalize(GKaitaiStream *stream)
+{
+ G_OBJECT_CLASS(g_kaitai_stream_parent_class)->finalize(G_OBJECT(stream));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire parcouru par une analyse Kaitai. *
+* pos = tête de lecture courante. *
+* *
+* Description : Rassemble les éléments constituant un flux de données Kaitai.*
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiStream *g_kaitai_stream_new(GBinContent *content, const vmpa2t *pos)
+{
+ GKaitaiStream *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_STREAM, NULL);
+
+ if (!g_kaitai_stream_create(result, content, pos))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à initialiser pleinement.*
+* content = contenu binaire parcouru par une analyse Kaitai. *
+* pos = tête de lecture courante. *
+* *
+* Description : Met en place un flux de données pour Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_stream_create(GKaitaiStream *stream, GBinContent *content, const vmpa2t *pos)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ stream->content = content;
+ g_object_ref(G_OBJECT(content));
+
+ copy_vmpa(&stream->pos, pos);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stream = flux de données Kaitai à consulter. *
+* *
+* Description : Indique le contenu de données binaires lié au flux Kaitai. *
+* *
+* Retour : Contenu binaire associé au flux de données. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *g_kaitai_stream_get_content(const GKaitaiStream *stream)
+{
+ GBinContent *result; /* Instance à renvoyer */
+
+ result = stream->content;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stream = flux de données Kaitai à consulter. *
+* *
+* Description : Détermine si la fin des données a été atteinte. *
+* *
+* Retour : true si la tête de lecture est en position finale, ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_stream_has_reached_eof(const GKaitaiStream *stream)
+{
+ bool result; /* Bilan à retourner */
+ vmpa2t end; /* Position finale du flux */
+ int ret; /* Bilan d'une comparaison */
+
+ g_binary_content_compute_end_pos(stream->content, &end);
+
+ ret = cmp_vmpa_by_phy(&stream->pos, &end);
+
+ result = (ret == 0);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/stream.h b/plugins/kaitai/stream.h
new file mode 100644
index 0000000..ee82c6d
--- /dev/null
+++ b/plugins/kaitai/stream.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_STREAM_H
+#define PLUGINS_KAITAI_STREAM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+
+
+
+#define G_TYPE_KAITAI_STREAM g_kaitai_stream_get_type()
+#define G_KAITAI_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_STREAM, GKaitaiStream))
+#define G_IS_KAITAI_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_STREAM))
+#define G_KAITAI_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_STREAM, GKaitaiStreamClass))
+#define G_IS_KAITAI_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_STREAM))
+#define G_KAITAI_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_STREAM, GKaitaiStreamClass))
+
+
+/* Flux de données à disposition d'une analyse Kaitai (instance) */
+typedef struct _GKaitaiStream GKaitaiStream;
+
+/* Flux de données à disposition d'une analyse Kaitai (classe) */
+typedef struct _GKaitaiStreamClass GKaitaiStreamClass;
+
+
+/* Indique le type défini pour un flux de données manipulé par une lecture Kaitai. */
+GType g_kaitai_stream_get_type(void);
+
+/* Rassemble les éléments constituant un flux de données Kaitai. */
+GKaitaiStream *g_kaitai_stream_new(GBinContent *, const vmpa2t *);
+
+/* Indique le contenu de données binaires lié au flux Kaitai. */
+GBinContent *g_kaitai_stream_get_content(const GKaitaiStream *);
+
+/* Détermine si la fin des données a été atteinte. */
+bool g_kaitai_stream_has_reached_eof(const GKaitaiStream *);
+
+
+
+#endif /* PLUGINS_KAITAI_STREAM_H */
diff --git a/plugins/kaitai/tokens.l b/plugins/kaitai/tokens.l
new file mode 100644
index 0000000..8c93299
--- /dev/null
+++ b/plugins/kaitai/tokens.l
@@ -0,0 +1,329 @@
+
+%top {
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+#include <common/extstr.h>
+
+#include "grammar.h"
+
+}
+
+
+%{
+
+#define PUSH_STATE(s) yy_push_state(s, yyscanner)
+#define POP_STATE yy_pop_state(yyscanner)
+
+%}
+
+
+%option bison-bridge reentrant
+%option stack
+%option nounput
+ //%option noinput
+%option noyywrap
+%option noyy_top_state
+%option yylineno
+%option never-interactive
+
+
+%x encoding
+%x escaped_str
+%x plain_str
+
+
+%%
+
+
+%{
+
+ /* no init C code */
+
+%}
+
+
+"+" { return PLUS; }
+"-" { return MINUS; }
+"*" { return MUL; }
+"/" { return DIV; }
+"%" { return MOD; }
+
+"<" { return LT; }
+"<=" { return LE; }
+"==" { return EQ; }
+"!=" { return NE; }
+">" { return GT; }
+">=" { return GE; }
+
+"<<" { return SHIFT_LEFT; }
+">>" { return SHIFT_RIGHT; }
+"&" { return BIT_AND; }
+"|" { return BIT_OR; }
+"^" { return BIT_XOR; }
+
+"not" { return NOT; }
+"and" { return AND; }
+"or" { return OR; }
+
+"(" { return PAREN_O; }
+")" { return PAREN_C; }
+"[" { return HOOK_O; }
+"]" { return HOOK_C; }
+"," { return COMMA; }
+"." { return DOT; }
+
+"?" { return QMARK; }
+":" { return COLON; }
+"::" { return DOUBLE_COLON; }
+
+".size" { return METH_SIZE; }
+".length" { return METH_LENGTH; }
+".reverse" { return METH_REVERSE; }
+".substring" { return METH_SUBSTRING; }
+".to_i" { return METH_TO_I; }
+".to_i(" { return METH_TO_I_RAD; }
+".to_s" { return METH_TO_S; }
+".to_s(" { PUSH_STATE(encoding); return METH_TO_S_ENC; }
+
+"_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; }
+
+
+%{ /* Lecteurs de valeurs entières */ %}
+
+0[bB][01]+ {
+ char *__end;
+ yylval->unsigned_integer = strtoull(yytext + 2, &__end, 2);
+ if (__end != (yytext + yyleng))
+ YY_FATAL_ERROR("failed to parse integer");
+ return UNSIGNED_INTEGER;
+ }
+
+0[bB][01]{1,4}(_[01]{4})+ {
+ char *__tmp;
+ char *__end;
+ __tmp = strdup(yytext);
+ __tmp = strrpl(__tmp, "_", "");
+ yylval->unsigned_integer = strtoull(__tmp + 2, &__end, 2);
+ if (__end != (__tmp + strlen(__tmp)))
+ {
+ free(__tmp);
+ YY_FATAL_ERROR("failed to parse integer");
+ }
+ else free(__tmp);
+ return UNSIGNED_INTEGER;
+ }
+
+(0|[1-9][0-9]*) {
+ char *__end;
+ yylval->unsigned_integer = strtoull(yytext, &__end, 10);
+ if (__end != (yytext + yyleng))
+ YY_FATAL_ERROR("failed to parse integer");
+ return UNSIGNED_INTEGER;
+ }
+
+[1-9][0-9]{0,2}(_[1-9][0-9]{2})+ {
+ char *__tmp;
+ char *__end;
+ __tmp = strdup(yytext);
+ __tmp = strrpl(__tmp, "_", "");
+ yylval->unsigned_integer = strtoull(__tmp, &__end, 10);
+ if (__end != (__tmp + strlen(__tmp)))
+ {
+ free(__tmp);
+ YY_FATAL_ERROR("failed to parse integer");
+ }
+ else free(__tmp);
+ return UNSIGNED_INTEGER;
+ }
+
+-(0|[1-9][0-9]*) {
+ char *__end;
+ yylval->signed_integer = strtoll(yytext, &__end, 10);
+ if (__end != (yytext + yyleng))
+ YY_FATAL_ERROR("failed to parse integer");
+ return SIGNED_INTEGER;
+ }
+
+-[1-9][0-9]{0,2}(_[1-9][0-9]{2})+ {
+ char *__tmp;
+ char *__end;
+ __tmp = strdup(yytext);
+ __tmp = strrpl(__tmp, "_", "");
+ yylval->signed_integer = strtoll(__tmp, &__end, 10);
+ if (__end != (__tmp + strlen(__tmp)))
+ {
+ free(__tmp);
+ YY_FATAL_ERROR("failed to parse integer");
+ }
+ else free(__tmp);
+ return SIGNED_INTEGER;
+ }
+
+0[xX][0-9a-fA-F]+ {
+ char *__end;
+ yylval->unsigned_integer = strtoull(yytext, &__end, 16);
+ if (__end != (yytext + yyleng))
+ YY_FATAL_ERROR("failed to parse integer");
+ return UNSIGNED_INTEGER;
+ }
+
+0[xX][0-9a-fA-F]{1,4}(_[0-9a-fA-F]{4})+ {
+ char *__tmp;
+ char *__end;
+ __tmp = strdup(yytext);
+ __tmp = strrpl(__tmp, "_", "");
+ yylval->unsigned_integer = strtoull(__tmp, &__end, 16);
+ if (__end != (__tmp + strlen(__tmp)))
+ {
+ free(__tmp);
+ YY_FATAL_ERROR("failed to parse integer");
+ }
+ else free(__tmp);
+ return UNSIGNED_INTEGER;
+ }
+
+
+
+-?(0|[1-9][0-9]*\.[0-9]+) {
+ char *__end;
+ yylval->floating_number = strtod(yytext, &__end);
+ if (__end != (yytext + yyleng))
+ YY_FATAL_ERROR("failed to parse float");
+ return FLOAT;
+ }
+
+
+%{ /* Paramètre d'encodage */ %}
+
+<encoding>["'][-_A-Za-z0-9 ]+["'] {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 2;
+ return ENCODING_NAME;
+ }
+
+<encoding>")" { POP_STATE; return PAREN_C; }
+
+
+[a-z][a-z0-9_]* {
+ yylval->sized_cstring.data = yytext;
+ yylval->sized_cstring.len = yyleng;
+ return IDENTIFIER;
+ }
+
+[^\\\[\],"'()\.: ]+ {
+ yylval->sized_cstring.data = yytext;
+ yylval->sized_cstring.len = yyleng;
+ return PLAIN_BYTES;
+ }
+
+
+%{ /* Lecteurs des tableaux de définition d'octets */ %}
+
+"\"" { PUSH_STATE(escaped_str); }
+
+
+<escaped_str>[^\\"]+ {
+ yylval->sized_cstring.data = yytext;
+ yylval->sized_cstring.len = yyleng;
+ return RAW_BYTES;
+ }
+
+<escaped_str>"\\a" { yylval->byte = '\a'; return RAW_BYTE; }
+<escaped_str>"\\b" { yylval->byte = '\b'; return RAW_BYTE; }
+<escaped_str>"\\t" { yylval->byte = '\t'; return RAW_BYTE; }
+<escaped_str>"\\n" { yylval->byte = '\n'; return RAW_BYTE; }
+<escaped_str>"\\v" { yylval->byte = '\v'; return RAW_BYTE; }
+<escaped_str>"\\f" { yylval->byte = '\f'; return RAW_BYTE; }
+<escaped_str>"\\r" { yylval->byte = '\r'; return RAW_BYTE; }
+<escaped_str>"\\e" { yylval->byte = '\e'; return RAW_BYTE; }
+<escaped_str>"\\\"" { yylval->byte = '"'; return RAW_BYTE; }
+<escaped_str>"\\'" { yylval->byte = '\''; return RAW_BYTE; }
+<escaped_str>"\\\\" { yylval->byte = '\\'; return RAW_BYTE; }
+<escaped_str>"\\0" { yylval->byte = '\0'; return RAW_BYTE; }
+
+<escaped_str>\\[0-9]{1,3} {
+ char __tmp[4];
+ memcpy(__tmp, yytext + 1, yyleng - 1);
+ __tmp[yyleng] = '\0';
+ yylval->byte = strtoull(__tmp, NULL, 8);
+ return RAW_BYTE;
+ }
+
+<escaped_str>"\"" { POP_STATE; }
+
+
+
+
+"'" { PUSH_STATE(plain_str); }
+
+<plain_str>[^']+ {
+ yylval->sized_cstring.data = yytext;
+ yylval->sized_cstring.len = yyleng;
+ return PLAIN_BYTES;
+ }
+
+<plain_str>['] { POP_STATE; }
+
+[.]$ {
+#ifndef NDEBUG
+ int ch;
+#endif
+ yylval->sized_cstring.data = yytext;
+ yylval->sized_cstring.len = yyleng;
+#ifndef NDEBUG
+ ch = input(yyscanner);
+ assert(ch == '\n');
+#else
+ input(yyscanner);
+#endif
+ return RAW_BYTES_WITH_ENDING_DOT;
+ }
+
+[^\\\[\],"'()\.: ]+[.]$ {
+#ifndef NDEBUG
+ int ch;
+#endif
+ yylval->sized_cstring.data = yytext;
+ yylval->sized_cstring.len = yyleng;
+#ifndef NDEBUG
+ ch = input(yyscanner);
+ assert(ch == '\n');
+#else
+ input(yyscanner);
+#endif
+ return RAW_BYTES_WITH_ENDING_DOT;
+ }
+
+
+%{ /* Actions par défaut */ %}
+
+<*>[ \t\n]+ { }
+
+<*>. {
+ char *msg;
+ int ret;
+ ret = asprintf(&msg,
+ "Unhandled token in rule definition: '%s'",
+ yytext);
+ if (ret == -1)
+ YY_FATAL_ERROR("Unhandled token in undisclosed rule definition");
+ else
+ {
+ YY_FATAL_ERROR(msg);
+ free(msg);
+ }
+ }
+
+
+%%
diff --git a/plugins/libcsem/Makefile.am b/plugins/libcsem/Makefile.am
index c55a2f8..a7a264f 100644
--- a/plugins/libcsem/Makefile.am
+++ b/plugins/libcsem/Makefile.am
@@ -15,10 +15,12 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN'
endif
-liblibcsem_la_SOURCES = \
- exit.h exit.c \
+liblibcsem_la_SOURCES = \
+ exit.h exit.c \
semantic.h semantic.c
+liblibcsem_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
liblibcsem_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -29,8 +31,3 @@ liblibcsem_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(liblibcsem_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/lnxsyscalls/Makefile.am b/plugins/lnxsyscalls/Makefile.am
index 9c5158f..21feaa5 100644
--- a/plugins/lnxsyscalls/Makefile.am
+++ b/plugins/lnxsyscalls/Makefile.am
@@ -14,17 +14,17 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN'
endif
-liblnxsyscalls_la_SOURCES = \
- collect.h collect.c \
- core.h core.c \
- db.h db.c \
- hops.h \
- hops_armv7.h hops_armv7.c \
- hunter.h hunter.c \
- syscall.h syscall.c \
+liblnxsyscalls_la_SOURCES = \
+ collect.h collect.c \
+ core.h core.c \
+ db.h db.c \
+ hops.h \
+ hops_armv7.h hops_armv7.c \
+ hunter.h hunter.c \
+ syscall.h syscall.c \
writer.h writer.c
-liblnxsyscalls_la_LIBADD =
+liblnxsyscalls_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
liblnxsyscalls_la_LDFLAGS = \
-avoid-version \
@@ -44,10 +44,3 @@ dbdir = $(pluginsdatadir)
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(liblnxsyscalls_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/lnxsyscalls/hunter.h b/plugins/lnxsyscalls/hunter.h
index ed191f4..c2040eb 100644
--- a/plugins/lnxsyscalls/hunter.h
+++ b/plugins/lnxsyscalls/hunter.h
@@ -26,7 +26,7 @@
#include <analysis/binary.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
#include "hops.h"
diff --git a/plugins/mobicore/Makefile.am b/plugins/mobicore/Makefile.am
index 761108e..e8616c2 100644
--- a/plugins/mobicore/Makefile.am
+++ b/plugins/mobicore/Makefile.am
@@ -11,13 +11,15 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs'
endif
-libmobicore_la_SOURCES = \
- core.h core.c \
- mclf-def.h \
- mclf-int.h mclf-int.c \
- mclf.h mclf.c \
+libmobicore_la_SOURCES = \
+ core.h core.c \
+ mclf-def.h \
+ mclf-int.h mclf-int.c \
+ mclf.h mclf.c \
symbols.h symbols.c
+libmobicore_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libmobicore_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -27,8 +29,3 @@ libmobicore_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libmobicore_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pe/Makefile.am b/plugins/pe/Makefile.am
index 038b8c5..e9cd482 100644
--- a/plugins/pe/Makefile.am
+++ b/plugins/pe/Makefile.am
@@ -37,19 +37,21 @@ PYTHON3_SUBDIRS = python
endif
-libpe_la_SOURCES = \
- core.h core.c \
- pe-int.h pe-int.c \
- format.h format.c \
- pe_def.h \
- rich.h rich.c \
- routine.h routine.c \
- section.h section.c \
+libpe_la_SOURCES = \
+ core.h core.c \
+ pe-int.h pe-int.c \
+ format.h format.c \
+ pe_def.h \
+ rich.h rich.c \
+ routine.h routine.c \
+ section.h section.c \
symbols.h symbols.c
-libpe_la_LIBADD = \
+libpe_la_LIBADD = \
$(PYTHON3_LIBADD)
+libpe_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libpe_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -61,8 +63,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpe_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/pe/core.c b/plugins/pe/core.c
index aa51c18..ddbacf5 100644
--- a/plugins/pe/core.c
+++ b/plugins/pe/core.c
@@ -24,18 +24,17 @@
#include "core.h"
-#include <config.h>
#include <core/global.h>
#include <plugins/self.h>
#include "format.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -65,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
result = add_format_pe_module_to_python_module();
#else
result = true;
diff --git a/plugins/pe/python/Makefile.am b/plugins/pe/python/Makefile.am
index 18634a3..5949821 100644
--- a/plugins/pe/python/Makefile.am
+++ b/plugins/pe/python/Makefile.am
@@ -1,23 +1,17 @@
noinst_LTLIBRARIES = libpepython.la
-libpepython_la_SOURCES = \
- constants.h constants.c \
- format.h format.c \
- module.h module.c \
- routine.h routine.c \
+libpepython_la_SOURCES = \
+ constants.h constants.c \
+ format.h format.c \
+ module.h module.c \
+ routine.h routine.c \
translate.h translate.c
-
-libpepython_la_LDFLAGS =
+libpepython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpepython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pe/python/format.c b/plugins/pe/python/format.c
index d295da4..4bbb99a 100644
--- a/plugins/pe/python/format.c
+++ b/plugins/pe/python/format.c
@@ -115,7 +115,7 @@ static PyObject *py_pe_format_new(PyTypeObject *type, PyObject *args, PyObject *
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -539,7 +539,10 @@ bool register_python_pe_format(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type, get_python_executable_format_type()))
+ if (!ensure_python_executable_format_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type))
return false;
if (!define_python_pe_format_constants(type))
diff --git a/plugins/pe/python/routine.c b/plugins/pe/python/routine.c
index cebeb2a..fd30e6d 100644
--- a/plugins/pe/python/routine.c
+++ b/plugins/pe/python/routine.c
@@ -221,7 +221,9 @@ bool register_python_pe_exported_routine(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PE_EXPORTED_ROUTINE, type, get_python_binary_routine_type()))
+ /* TODO : ensure get_python_binary_routine_type() */
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PE_EXPORTED_ROUTINE, type))
return false;
if (!define_python_pe_exported_routine_constants(type))
@@ -461,7 +463,9 @@ bool register_python_pe_imported_routine(PyObject *module)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PE_IMPORTED_ROUTINE, type, get_python_pe_exported_routine_type()))
+ /* TODO : ensure get_python_pe_exported_routine_type() */
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PE_IMPORTED_ROUTINE, type))
return false;
return true;
diff --git a/plugins/pe/symbols.h b/plugins/pe/symbols.h
index bb260cd..5c4b796 100644
--- a/plugins/pe/symbols.h
+++ b/plugins/pe/symbols.h
@@ -29,7 +29,7 @@
#include <glibext/delayed.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am
index fb3986c..4b6e551 100644
--- a/plugins/pychrysalide/Makefile.am
+++ b/plugins/pychrysalide/Makefile.am
@@ -13,32 +13,52 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN/chrysalide-libs'
endif
-pychrysalide_la_SOURCES = \
- access.h access.c \
- core.h core.c \
- helpers.h helpers.c \
- star.h star.c \
- strenum.h strenum.c \
- struct.h struct.c \
- weak.h weak.c
-
-pychrysalide_la_LIBADD = \
- analysis/libpychrysaanalysis.la \
- arch/libpychrysaarch.la \
- common/libpychrysacommon.la \
- core/libpychrysacore.la \
- debug/libpychrysadebug.la \
- format/libpychrysaformat.la \
- glibext/libpychrysaglibext.la \
- gtkext/libpychrysagtkext.la \
- gui/libpychrysagui.la \
- mangling/libpychrysamangling.la \
+if BUILD_GTK_SUPPORT
+
+GTKEXT_LIBADD = \
+ gtkext/libpychrysagtkext.la
+
+GTKEXT_SUBDIR = \
+ gtkext
+
+GUI_LIBADD = \
+ gui/libpychrysagui.la
+
+GUI_SUBDIR = \
+ gui
+
+endif
+
+
+pychrysalide_la_SOURCES = \
+ access.h access.c \
+ core.h core.c \
+ helpers.h helpers.c \
+ star.h star.c \
+ strenum.h strenum.c \
+ struct.h struct.c
+
+AM_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+pychrysalide_la_LIBADD = \
+ analysis/libpychrysaanalysis.la \
+ arch/libpychrysaarch.la \
+ common/libpychrysacommon.la \
+ core/libpychrysacore.la \
+ debug/libpychrysadebug.la \
+ format/libpychrysaformat.la \
+ glibext/libpychrysaglibext.la \
+ $(GTKEXT_LIBADD) \
+ $(GUI_LIBADD) \
+ mangling/libpychrysamangling.la \
plugins/libpychrysaplugins.la
# -ldl: dladdr(), dlerror()
pychrysalide_la_LDFLAGS = \
-module -avoid-version -ldl \
- $(LIBPYTHON_LIBS) $(LIBPYGOBJECT_LIBS) \
+ $(LIBPYTHON_INTERPRETER_LIBS) \
+ $(LIBPYGOBJECT_LIBS) \
-L$(top_srcdir)/src/.libs -lchrysacore \
$(RUN_PATH)
@@ -48,9 +68,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(pychrysalide_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS = analysis arch common core debug format glibext gtkext gui mangling plugins
+SUBDIRS = analysis arch common core debug format glibext $(GTKEXT_SUBDIR) $(GUI_SUBDIR) mangling plugins
diff --git a/plugins/pychrysalide/analysis/Makefile.am b/plugins/pychrysalide/analysis/Makefile.am
index d09cced..43e8ed2 100644
--- a/plugins/pychrysalide/analysis/Makefile.am
+++ b/plugins/pychrysalide/analysis/Makefile.am
@@ -1,28 +1,30 @@
noinst_LTLIBRARIES = libpychrysaanalysis.la
-libpychrysaanalysis_la_SOURCES = \
- binary.h binary.c \
- block.h block.c \
- cattribs.h cattribs.c \
- constants.h constants.c \
- content.h content.c \
- loaded.h loaded.c \
- loading.h loading.c \
- module.h module.c \
- project.h project.c \
- routine.h routine.c \
- type.h type.c \
+libpychrysaanalysis_la_SOURCES = \
+ binary.h binary.c \
+ block.h block.c \
+ cattribs.h cattribs.c \
+ constants.h constants.c \
+ content.h content.c \
+ loaded.h loaded.c \
+ loading.h loading.c \
+ module.h module.c \
+ project.h project.c \
+ routine.h routine.c \
+ type.h type.c \
variable.h variable.c
libpychrysaanalysis_la_LIBADD = \
contents/libpychrysaanalysiscontents.la \
db/libpychrysaanalysisdb.la \
disass/libpychrysaanalysisdisass.la \
+ scan/libpychrysaanalysisscan.la \
storage/libpychrysaanalysisstorage.la \
types/libpychrysaanalysistypes.la
-libpychrysaanalysis_la_LDFLAGS =
+libpychrysaanalysis_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -30,9 +32,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysis_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS = contents db disass storage types
+SUBDIRS = contents db disass scan storage types
diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c
index 68f2d88..6599ecc 100644
--- a/plugins/pychrysalide/analysis/binary.c
+++ b/plugins/pychrysalide/analysis/binary.c
@@ -124,15 +124,13 @@ static PyObject *py_loaded_binary_new(PyTypeObject *type, PyObject *args, PyObje
static PyObject *py_loaded_binary_get_client(PyObject *self, PyObject *args)
{
PyObject *result; /* Bilan à retourner */
- int internal; /* Nature du client visé */
- int ret; /* Bilan de lecture des args. */
GLoadedBinary *binary; /* Binaire en cours d'analyse */
GAnalystClient *client; /* Eventuel client en place */
#define LOADED_BINARY_GET_CLIENT_METHOD PYTHON_METHOD_DEF \
( \
- get_client, "$self, /, internal=True", \
- METH_VARARGS, py_loaded_binary, \
+ get_client, "$self", \
+ METH_NOARGS, py_loaded_binary, \
"Provide the client connected to an internal or remote server" \
" if defined, or return None otherwise.\n" \
"\n" \
@@ -140,14 +138,9 @@ static PyObject *py_loaded_binary_get_client(PyObject *self, PyObject *args)
" instance or *None*." \
)
- internal = 1;
-
- ret = PyArg_ParseTuple(args, "|p", &internal);
- if (!ret) return NULL;
-
binary = G_LOADED_BINARY(pygobject_get(self));
- client = g_loaded_binary_get_client(binary, internal);
+ client = g_loaded_binary_get_client(binary);
if (client != NULL)
{
@@ -569,7 +562,7 @@ bool ensure_python_loaded_binary_is_registered(void)
if (!ensure_python_loaded_content_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_LOADED_BINARY, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_LOADED_BINARY, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c
index 0b09eb7..7f74c2f 100644
--- a/plugins/pychrysalide/analysis/block.c
+++ b/plugins/pychrysalide/analysis/block.c
@@ -353,7 +353,7 @@ bool ensure_python_code_block_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_CODE_BLOCK, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_CODE_BLOCK, type))
return false;
}
@@ -612,7 +612,7 @@ bool ensure_python_block_list_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BLOCK_LIST, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BLOCK_LIST, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/cattribs.c b/plugins/pychrysalide/analysis/cattribs.c
index be5c5b1..84a5e1d 100644
--- a/plugins/pychrysalide/analysis/cattribs.c
+++ b/plugins/pychrysalide/analysis/cattribs.c
@@ -45,9 +45,6 @@ static PyObject *py_content_attributes_new(PyTypeObject *, PyObject *, PyObject
/* Fournit l'ensemble des clefs d'un ensemble d'attributs. */
static PyObject *py_content_attributes_subscript(PyObject *, PyObject *);
-/* Fournit le fichier de base compris dans le chemin initial. */
-static PyObject *py_content_attributes_get_filename(PyObject *, void *);
-
/* Fournit l'ensemble des clefs d'un ensemble d'attributs. */
static PyObject *py_content_attributes_get_keys(PyObject *, void *);
@@ -72,7 +69,10 @@ static PyObject *py_content_attributes_new(PyTypeObject *type, PyObject *args, P
PyObject *result; /* Instance à retourner */
const char *path; /* Chemin d'accès à traiter */
int ret; /* Bilan de lecture des args. */
+ char *filename; /* Nom de fichier embarqué */
GContentAttributes *attribs; /* Création GLib à transmettre */
+ PyObject *obj; /* Objet Python à retourner */
+ PyObject *str; /* Chaîne à retourner */
#define CONTENT_ATTRIBUTES_DOC \
"ContentAttributes is a set of values used at binary content loading.\n" \
@@ -87,25 +87,43 @@ static PyObject *py_content_attributes_new(PyTypeObject *type, PyObject *args, P
"\n" \
" ContentAttributes(path)\n" \
"\n" \
- "Where path is a list of parameters: '[...]&key0=value0&key1=value1...'"
+ "Where path is a list of parameters: '[...]&key0=value0&key1=value1...'" \
+ "\n" \
+ "The constructor returns a tuple containing a ContentAttributes instance" \
+ " and the original targot filename."
ret = PyArg_ParseTuple(args, "s", &path);
if (!ret) return NULL;
- attribs = g_content_attributes_new(path);
+ attribs = g_content_attributes_new(path, &filename);
if (attribs != NULL)
{
g_object_ref_sink(G_OBJECT(attribs));
- result = pygobject_new(G_OBJECT(attribs));
+ obj = pygobject_new(G_OBJECT(attribs));
g_object_unref(attribs);
}
else
{
- result = Py_None;
- Py_INCREF(result);
+ obj = Py_None;
+ Py_INCREF(obj);
}
+ if (filename != NULL)
+ {
+ str = PyUnicode_FromString(filename);
+ free(filename);
+ }
+ else
+ {
+ str = Py_None;
+ Py_INCREF(str);
+ }
+
+ result = PyTuple_New(2);
+ PyTuple_SetItem(result, 0, obj);
+ PyTuple_SetItem(result, 1, str);
+
return result;
}
@@ -200,50 +218,6 @@ static PyObject *py_content_attributes_get_keys(PyObject *self, void *closure)
/******************************************************************************
* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit le fichier de base compris dans le chemin initial. *
-* *
-* Retour : Nom de fichier renvoyant vers un contenu à charger ou None. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_content_attributes_get_filename(PyObject *self, void *closure)
-{
- PyObject *result; /* Valeur à retourner */
- GContentAttributes *cattribs; /* Version native */
- const char *filename; /* Nom de fichier natif */
-
-#define CONTENT_ATTRIBUTES_FILENAME_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- filename, py_content_attributes, \
- "Filename extracted from the path provided to the attribute set," \
- " constructor, or None if no filename was defined." \
-)
-
- cattribs = G_CONTENT_ATTRIBUTES(pygobject_get(self));
-
- filename = g_content_attributes_get_filename(cattribs);
-
- if (filename != NULL)
- result = PyUnicode_FromString(filename);
-
- else
- {
- result = Py_None;
- Py_INCREF(result);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -267,7 +241,6 @@ PyTypeObject *get_python_content_attributes_type(void)
};
static PyGetSetDef py_content_attributes_getseters[] = {
- CONTENT_ATTRIBUTES_FILENAME_ATTRIB,
CONTENT_ATTRIBUTES_KEYS_ATTRIB,
{ NULL }
};
@@ -321,7 +294,7 @@ bool ensure_python_content_attributes_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_ATTRIBUTES, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_ATTRIBUTES, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c
index 68ecba2..c30cdd8 100644
--- a/plugins/pychrysalide/analysis/content.c
+++ b/plugins/pychrysalide/analysis/content.c
@@ -40,6 +40,7 @@
#include "cattribs.h"
#include "constants.h"
+#include "storage/serialize.h"
#include "../access.h"
#include "../helpers.h"
#include "../arch/vmpa.h"
@@ -49,8 +50,13 @@
/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Procède à l'initialisation de l'interface de génération. */
-static void py_binary_content_interface_init(GBinContentIface *, gpointer *);
+/* Initialise la classe générique des contenus de binaire. */
+static void py_binary_content_init_gclass(GBinContentClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(binary_content, G_TYPE_BIN_CONTENT, py_binary_content_init_gclass);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_binary_content_init(PyObject *, PyObject *, PyObject *);
/* Fournit le nom associé au contenu binaire. */
static char *py_binary_content_describe_wrapper(const GBinContent *, bool);
@@ -99,6 +105,9 @@ static int py_binary_content_set_attributes(PyObject *, PyObject *, void *);
/* Fournit l'ensemble des attributs associés à un contenu. */
static PyObject *py_binary_content_get_attributes(PyObject *, void *);
+/* Donne l'origine d'un contenu binaire. */
+static PyObject *py_binary_content_get_root(PyObject *, void *);
+
/* Fournit une empreinte unique (SHA256) pour les données. */
static PyObject *py_binary_content_get_checksum(PyObject *, void *);
@@ -123,10 +132,10 @@ static PyObject *py_binary_content_get_data(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : iface = interface GLib à initialiser. *
-* unused = adresse non utilisée ici. *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
* *
-* Description : Procède à l'initialisation de l'interface de génération. *
+* Description : Initialise la classe générique des contenus de binaire. *
* *
* Retour : - *
* *
@@ -134,21 +143,45 @@ static PyObject *py_binary_content_get_data(PyObject *, void *);
* *
******************************************************************************/
-static void py_binary_content_interface_init(GBinContentIface *iface, gpointer *unused)
+static void py_binary_content_init_gclass(GBinContentClass *class, gpointer unused)
+{
+ class->describe = py_binary_content_describe_wrapper;
+
+ class->read_raw = py_binary_content_read_raw_wrapper;
+ class->read_u8 = py_binary_content_read_u8_wrapper;
+ class->read_u16 = py_binary_content_read_u16_wrapper;
+ class->read_u32 = py_binary_content_read_u32_wrapper;
+ class->read_u64 = py_binary_content_read_u64_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_binary_content_init(PyObject *self, PyObject *args, PyObject *kwds)
{
+ int ret; /* Bilan de lecture des args. */
+
#define BINARY_CONTENT_DOC \
- "The BinContent is an interface which handles access to a given binary" \
- " content.\n" \
+ "A BinContent is an abstract object which handles access to a given" \
+ " binary content.\n" \
"\n" \
"All of its implementations are located in the" \
" pychrysalide.analysis.contents module. The main implemantation is" \
" the pychrysalide.analysis.contents.FileContent class.\n" \
"\n" \
- "A typical class declaration for a new implementation looks like:\n" \
- "\n" \
- " class NewImplem(GObject.Object, BinContent):\n" \
- " ...\n" \
- "\n" \
"The following methods have to be defined for new implementations:\n" \
"* pychrysalide.analysis.BinContent._describe();\n" \
"* pychrysalide.analysis.BinContent._read_raw();\n" \
@@ -158,13 +191,12 @@ static void py_binary_content_interface_init(GBinContentIface *iface, gpointer *
"* pychrysalide.analysis.BinContent._read_u32();\n" \
"* pychrysalide.analysis.BinContent._read_u64();\n"
- iface->describe = py_binary_content_describe_wrapper;
+ /* Initialisation d'un objet GLib */
- iface->read_raw = py_binary_content_read_raw_wrapper;
- iface->read_u8 = py_binary_content_read_u8_wrapper;
- iface->read_u16 = py_binary_content_read_u16_wrapper;
- iface->read_u32 = py_binary_content_read_u32_wrapper;
- iface->read_u64 = py_binary_content_read_u64_wrapper;
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
}
@@ -1133,6 +1165,48 @@ static PyObject *py_binary_content_get_attributes(PyObject *self, void *closure)
* Paramètres : self = contenu binaire à manipuler. *
* closure = adresse non utilisée ici. *
* *
+* Description : Donne l'origine d'un contenu binaire. *
+* *
+* Retour : Contenu à l'origine du contenu courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_binary_content_get_root(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance à retourner */
+ GBinContent *content; /* Version GLib du format */
+ GContentAttributes *attribs; /* Attributs à transmettre */
+
+#define BINARY_CONTENT_ROOT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ root, py_binary_content, \
+ "Provide, as a pychrysalide.analysis.BinContent instance, the root" \
+ " content leading to the current content." \
+ "\n" \
+ "This property is relevant only for" \
+ " pychrysalide.analysis.contents.EncapsulatedContent objects." \
+)
+
+ content = G_BIN_CONTENT(pygobject_get(self));
+
+ attribs = g_binary_content_get_attributes(content);
+
+ result = pygobject_new(G_OBJECT(attribs));
+
+ g_object_unref(attribs);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = contenu binaire à manipuler. *
+* closure = adresse non utilisée ici. *
+* *
* Description : Fournit une empreinte unique (SHA256) pour les données. *
* *
* Retour : Bilan de l'opération. *
@@ -1347,6 +1421,7 @@ PyTypeObject *get_python_binary_content_type(void)
static PyGetSetDef py_binary_content_getseters[] = {
BINARY_CONTENT_ATTRIBUTES_ATTRIB,
+ BINARY_CONTENT_ROOT_ATTRIB,
BINARY_CONTENT_CHECKSUM_ATTRIB,
BINARY_CONTENT_SIZE_ATTRIB,
BINARY_CONTENT_START_POS_ATTRIB,
@@ -1360,14 +1435,17 @@ PyTypeObject *get_python_binary_content_type(void)
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "pychrysalide.analysis.BinContent",
- .tp_basicsize = sizeof(PyObject),
+ .tp_basicsize = sizeof(PyGObject),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = BINARY_CONTENT_DOC,
.tp_methods = py_binary_content_methods,
- .tp_getset = py_binary_content_getseters
+ .tp_getset = py_binary_content_getseters,
+
+ .tp_init = py_binary_content_init,
+ .tp_new = py_binary_content_new,
};
@@ -1394,23 +1472,18 @@ bool ensure_python_binary_content_is_registered(void)
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- static GInterfaceInfo info = { /* Paramètres d'inscription */
-
- .interface_init = (GInterfaceInitFunc)py_binary_content_interface_init,
- .interface_finalize = NULL,
- .interface_data = NULL,
-
- };
-
type = get_python_binary_content_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
+ if (!ensure_python_serializable_object_is_registered())
+ return false;
+
module = get_access_to_python_module("pychrysalide.analysis");
dict = PyModule_GetDict(module);
- if (!register_interface_for_pygobject(dict, G_TYPE_BIN_CONTENT, type, &info))
+ if (!register_class_for_pygobject(dict, G_TYPE_BIN_CONTENT, type))
return false;
if (!define_analysis_content_constants(type))
diff --git a/plugins/pychrysalide/analysis/contents/Makefile.am b/plugins/pychrysalide/analysis/contents/Makefile.am
index 07fafd0..9238a58 100644
--- a/plugins/pychrysalide/analysis/contents/Makefile.am
+++ b/plugins/pychrysalide/analysis/contents/Makefile.am
@@ -1,22 +1,17 @@
noinst_LTLIBRARIES = libpychrysaanalysiscontents.la
-libpychrysaanalysiscontents_la_SOURCES = \
- encapsulated.h encapsulated.c \
- file.h file.c \
- memory.h memory.c \
- module.h module.c \
+libpychrysaanalysiscontents_la_SOURCES = \
+ encapsulated.h encapsulated.c \
+ file.h file.c \
+ memory.h memory.c \
+ module.h module.c \
restricted.h restricted.c
-libpychrysaanalysiscontents_la_LDFLAGS =
+libpychrysaanalysiscontents_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysiscontents_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/analysis/contents/encapsulated.c b/plugins/pychrysalide/analysis/contents/encapsulated.c
index ef26caa..e9583e6 100644
--- a/plugins/pychrysalide/analysis/contents/encapsulated.c
+++ b/plugins/pychrysalide/analysis/contents/encapsulated.c
@@ -28,7 +28,8 @@
#include <pygobject.h>
-#include <analysis/contents/encapsulated.h>
+#include <i18n.h>
+#include <analysis/contents/encapsulated-int.h>
#include "../content.h"
@@ -37,8 +38,10 @@
-/* Crée un nouvel objet Python de type 'BinContent'. */
-static PyObject *py_encaps_content_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(encaps_content, G_TYPE_ENCAPS_CONTENT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_encaps_content_init(PyObject *, PyObject *, PyObject *);
/* Indique la base d'un contenu binaire encapsulé. */
static PyObject *py_encaps_content_get_base(PyObject *, void *);
@@ -53,26 +56,25 @@ static PyObject *py_encaps_content_get_endpoint(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'BinContent'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_encaps_content_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
GBinContent *base; /* Base de l'extraction */
const char *path; /* Chemin vers le contenu final*/
GBinContent *endpoint; /* Contenu accessible au final */
int ret; /* Bilan de lecture des args. */
- GBinContent *content; /* Version GLib du contenu */
+ GEncapsContent *content; /* Version GLib du contenu */
#define ENCAPS_CONTENT_DOC \
"EncapsulatedContent gathers items relative to a binary encapsulated" \
@@ -93,20 +95,30 @@ static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObj
" pychrysalide.analysis.BinContent instances and the access path must" \
" be provided as a string."
+ /* Récupération des paramètres */
+
ret = PyArg_ParseTuple(args, "O&sO&",
convert_to_binary_content, &base,
&path,
convert_to_binary_content, &endpoint);
- if (!ret) return NULL;
+ if (!ret) return -1;
- content = g_encaps_content_new(base, path, endpoint);
+ /* Initialisation d'un objet GLib */
- result = pygobject_new(G_OBJECT(content));
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
- if (content != NULL)
- g_object_unref(content);
+ /* Eléments de base */
- return result;
+ content = G_ENCAPS_CONTENT(pygobject_get(self));
+
+ if (!g_encaps_content_create(content, base, path, endpoint))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create encapsulated content."));
+ return -1;
+ }
+
+ return 0;
}
@@ -275,7 +287,9 @@ PyTypeObject *get_python_encaps_content_type(void)
.tp_methods = py_encaps_content_methods,
.tp_getset = py_encaps_content_getseters,
- .tp_new = py_encaps_content_new
+
+ .tp_init = py_encaps_content_init,
+ .tp_new = py_encaps_content_new,
};
@@ -310,7 +324,10 @@ bool ensure_python_encaps_content_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ENCAPS_CONTENT, type, &PyGObject_Type))
+ if (!ensure_python_binary_content_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ENCAPS_CONTENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/contents/file.c b/plugins/pychrysalide/analysis/contents/file.c
index 93a1ce8..5bef069 100644
--- a/plugins/pychrysalide/analysis/contents/file.c
+++ b/plugins/pychrysalide/analysis/contents/file.c
@@ -28,16 +28,20 @@
#include <pygobject.h>
-#include <analysis/contents/file.h>
+#include <i18n.h>
+#include <analysis/contents/file-int.h>
+#include "memory.h"
#include "../../access.h"
#include "../../helpers.h"
-/* Crée un nouvel objet Python de type 'BinContent'. */
-static PyObject *py_file_content_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(file_content, G_TYPE_FILE_CONTENT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_file_content_init(PyObject *, PyObject *, PyObject *);
/* Fournit le nom de fichier associé au contenu binaire. */
static PyObject *py_file_content_get_filename(PyObject *, void *);
@@ -46,24 +50,23 @@ static PyObject *py_file_content_get_filename(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'BinContent'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_file_content_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
const char *filename; /* Nom du fichier à charger */
int ret; /* Bilan de lecture des args. */
- GBinContent *content; /* Version GLib du contenu */
+ GFileContent *content; /* Version GLib du contenu */
#define FILE_CONTENT_DOC \
"FileContent handles binary content loaded from a file.\n" \
@@ -74,17 +77,27 @@ static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObjec
"\n" \
"Where filename is a path to an existing file."
+ /* Récupération des paramètres */
+
ret = PyArg_ParseTuple(args, "s", &filename);
- if (!ret) return NULL;
+ if (!ret) return -1;
- content = g_file_content_new(filename);
+ /* Initialisation d'un objet GLib */
- result = pygobject_new(G_OBJECT(content));
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
- if (content != NULL)
- g_object_unref(content);
+ /* Eléments de base */
- return result;
+ content = G_FILE_CONTENT(pygobject_get(self));
+
+ if (!g_file_content_create(content, filename))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create file content."));
+ return -1;
+ }
+
+ return 0;
}
@@ -161,7 +174,9 @@ PyTypeObject *get_python_file_content_type(void)
.tp_methods = py_file_content_methods,
.tp_getset = py_file_content_getseters,
- .tp_new = py_file_content_new
+
+ .tp_init = py_file_content_init,
+ .tp_new = py_file_content_new,
};
@@ -196,7 +211,10 @@ bool ensure_python_file_content_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_FILE_CONTENT, type, &PyGObject_Type))
+ if (!ensure_python_memory_content_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_FILE_CONTENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/contents/memory.c b/plugins/pychrysalide/analysis/contents/memory.c
index 8926300..7464779 100644
--- a/plugins/pychrysalide/analysis/contents/memory.c
+++ b/plugins/pychrysalide/analysis/contents/memory.c
@@ -28,40 +28,43 @@
#include <pygobject.h>
-#include <analysis/contents/memory.h>
+#include <i18n.h>
+#include <analysis/contents/memory-int.h>
+#include "../content.h"
#include "../../access.h"
#include "../../helpers.h"
-/* Crée un nouvel objet Python de type 'BinContent'. */
-static PyObject *py_memory_content_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(memory_content, G_TYPE_MEMORY_CONTENT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_memory_content_init(PyObject *, PyObject *, PyObject *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'BinContent'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_memory_content_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
const char *data; /* Tampon interne de Python */
- int length; /* Taille utilisé de ce tampon */
+ Py_ssize_t length; /* Taille utilisé de ce tampon */
int ret; /* Bilan de lecture des args. */
- GBinContent *content; /* Version GLib du contenu */
+ GMemoryContent *content; /* Version GLib du contenu */
#define MEMORY_CONTENT_DOC \
"MemoryContent builds a binary content from memory data only." \
@@ -74,22 +77,32 @@ static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObj
"Where data is provided as string or read-only bytes-like object." \
" The string may contain embedded null bytes."
+ /* Récupération des paramètres */
+
/**
* La taille doit être de type 'int' et non 'Py_ssize_t', sinon les 32 bits
* de poids fort ne sont pas initialisés !
*/
ret = PyArg_ParseTuple(args, "s#", &data, &length);
- if (!ret) return NULL;
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
- content = g_memory_content_new((const bin_t *)data, length);
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
- result = pygobject_new(G_OBJECT(content));
+ /* Eléments de base */
- if (content != NULL)
- g_object_unref(content);
+ content = G_MEMORY_CONTENT(pygobject_get(self));
- return result;
+ if (!g_memory_content_create(content, (const bin_t *)data, length))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create memory content."));
+ return -1;
+ }
+
+ return 0;
}
@@ -129,7 +142,9 @@ PyTypeObject *get_python_memory_content_type(void)
.tp_methods = py_memory_content_methods,
.tp_getset = py_memory_content_getseters,
- .tp_new = py_memory_content_new
+
+ .tp_init = py_memory_content_init,
+ .tp_new = py_memory_content_new,
};
@@ -152,7 +167,7 @@ PyTypeObject *get_python_memory_content_type(void)
bool ensure_python_memory_content_is_registered(void)
{
- PyTypeObject *type; /* Type Python 'MemoryContent' */
+ PyTypeObject *type; /* Type Python 'MemoryContent' */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
@@ -164,7 +179,10 @@ bool ensure_python_memory_content_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_MEMORY_CONTENT, type, &PyGObject_Type))
+ if (!ensure_python_binary_content_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_MEMORY_CONTENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/contents/restricted.c b/plugins/pychrysalide/analysis/contents/restricted.c
index bbe364a..4521578 100644
--- a/plugins/pychrysalide/analysis/contents/restricted.c
+++ b/plugins/pychrysalide/analysis/contents/restricted.c
@@ -31,7 +31,8 @@
#include <i18n.h>
-#include <analysis/contents/restricted.h>
+#include <i18n.h>
+#include <analysis/contents/restricted-int.h>
#include "../content.h"
@@ -41,8 +42,10 @@
-/* Crée un nouvel objet Python de type 'BinContent'. */
-static PyObject *py_restricted_content_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(restricted_content, G_TYPE_RESTRICTED_CONTENT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_restricted_content_init(PyObject *, PyObject *, PyObject *);
/* Indique l'espace de restriction appliqué à un contenu. */
static PyObject *py_restricted_content_get_range(PyObject *, void *);
@@ -51,25 +54,24 @@ static PyObject *py_restricted_content_get_range(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'BinContent'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_restricted_content_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
- GBinContent *content; /* Instance GLib correspondante*/
+ GBinContent *internal; /* Instance GLib correspondante*/
mrange_t range; /* Restriction à appliquer */
int ret; /* Bilan de lecture des args. */
- GBinContent *restricted; /* Création GLib à transmettre */
+ GRestrictedContent *content; /* Version GLib du contenu */
#define RESTRICTED_CONTENT_DOC \
"RestrictedContent restricts access to a given area for a binary content." \
@@ -81,14 +83,27 @@ static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, P
"Where content is a pychrysalide.analysis.BinContent instance and range" \
" a Python object which can be converted into pychrysalide.arch.mrange."
- ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &content, convert_any_to_mrange, &range);
- if (!ret) return NULL;
+ /* Récupération des paramètres */
- restricted = g_restricted_content_new(content, &range);
+ ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &internal, convert_any_to_mrange, &range);
+ if (!ret) return -1;
- result = pygobject_new(G_OBJECT(restricted));
+ /* Initialisation d'un objet GLib */
- return result;
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ content = G_RESTRICTED_CONTENT(pygobject_get(self));
+
+ if (!g_restricted_content_create(content, internal, &range))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create restricted content."));
+ return -1;
+ }
+
+ return 0;
}
@@ -165,7 +180,9 @@ PyTypeObject *get_python_restricted_content_type(void)
.tp_methods = py_restricted_content_methods,
.tp_getset = py_restricted_content_getseters,
- .tp_new = py_restricted_content_new
+
+ .tp_init = py_restricted_content_init,
+ .tp_new = py_restricted_content_new,
};
@@ -200,7 +217,10 @@ bool ensure_python_restricted_content_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_RESTRICTED_CONTENT, type, &PyGObject_Type))
+ if (!ensure_python_binary_content_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_RESTRICTED_CONTENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/Makefile.am b/plugins/pychrysalide/analysis/db/Makefile.am
index 721f5b6..a0dcc0d 100644
--- a/plugins/pychrysalide/analysis/db/Makefile.am
+++ b/plugins/pychrysalide/analysis/db/Makefile.am
@@ -1,21 +1,22 @@
noinst_LTLIBRARIES = libpychrysaanalysisdb.la
-libpychrysaanalysisdb_la_SOURCES = \
- admin.h admin.c \
- analyst.h analyst.c \
- certs.h certs.c \
- client.h client.c \
- collection.h collection.c \
- constants.h constants.c \
- item.h item.c \
- module.h module.c \
+libpychrysaanalysisdb_la_SOURCES = \
+ admin.h admin.c \
+ analyst.h analyst.c \
+ certs.h certs.c \
+ client.h client.c \
+ collection.h collection.c \
+ constants.h constants.c \
+ item.h item.c \
+ module.h module.c \
server.h server.c
-libpychrysaanalysisdb_la_LIBADD = \
+libpychrysaanalysisdb_la_LIBADD = \
items/libpychrysaanalysisdbitems.la
-libpychrysaanalysisdb_la_LDFLAGS =
+libpychrysaanalysisdb_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -23,9 +24,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysisdb_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = items
diff --git a/plugins/pychrysalide/analysis/db/admin.c b/plugins/pychrysalide/analysis/db/admin.c
index a4694e6..10a150e 100644
--- a/plugins/pychrysalide/analysis/db/admin.c
+++ b/plugins/pychrysalide/analysis/db/admin.c
@@ -237,7 +237,7 @@ PyTypeObject *get_python_admin_client_type(void)
* *
* Paramètres : module = module dont la définition est à compléter. *
* *
-* Description : Prend en charge l'objet 'pychrysalide....db.AdminClient'. *
+* Description : Prend en charge l'objet 'pychrysalide....db.AdminClient'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -255,14 +255,14 @@ bool ensure_python_admin_client_is_registered(void)
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
- if (!ensure_python_hub_client_is_registered())
- return false;
-
module = get_access_to_python_module("pychrysalide.analysis.db");
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ADMIN_CLIENT, type, get_python_hub_client_type()))
+ if (!ensure_python_hub_client_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ADMIN_CLIENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/analyst.c b/plugins/pychrysalide/analysis/db/analyst.c
index 83e3878..f2860ed 100644
--- a/plugins/pychrysalide/analysis/db/analyst.c
+++ b/plugins/pychrysalide/analysis/db/analyst.c
@@ -30,20 +30,26 @@
#include <i18n.h>
-#include <analysis/db/analyst.h>
+#include <analysis/db/analyst-int.h>
#include <core/collections.h>
#include "client.h"
#include "collection.h"
+#include "constants.h"
+#include "../content.h"
+#include "../loaded.h"
#include "../../access.h"
#include "../../helpers.h"
#include "../../struct.h"
-/* Crée un nouvel objet Python de type 'AnalystClient'. */
-static PyObject *py_analyst_client_new(PyTypeObject *, PyObject *, PyObject *);
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_analyst_client_init(PyObject *, PyObject *, PyObject *);
+
+/* Envoie un contenu binaire pour conservation côté serveur. */
+static PyObject *py_analyst_client_send_content(PyObject *, PyObject *);
/* Effectue une demande de sauvegarde de l'état courant. */
static PyObject *py_analyst_client_save(PyObject *, PyObject *);
@@ -74,24 +80,29 @@ static PyObject *py_analyst_client_get_current_snapshot(PyObject *, void *);
+CREATE_DYN_CONSTRUCTOR(analyst_client, G_TYPE_ANALYST_CLIENT);
+
+
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'AnalystClient'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_analyst_client_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
+ int result; /* Bilan à retourner */
+ GLoadedContent *loaded; /* Contenu local déjà chargé */
const char *hash; /* Empreinte du binaire visé */
+ const char *class; /* Nature du contenu analysé */
PyObject *list; /* Liste Python de collections */
int ret; /* Bilan de lecture des args. */
Py_ssize_t length; /* Nombre d'éléments collectés */
@@ -99,7 +110,8 @@ static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObj
Py_ssize_t i; /* Boucle de parcours */
PyObject *item; /* Elément de la liste Python */
GDbCollection *collec; /* Version équivalente native */
- GAnalystClient *client; /* Serveur mis en place */
+ GAnalystClient *client; /* Client mis en place */
+ bool status; /* Bilan d'initialisation */
#define ANALYST_CLIENT_DOC \
"AnalystClient provides and receives binary updates to and from a connected" \
@@ -109,11 +121,15 @@ static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObj
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " AnalystClient(hash, list)" \
+ " AnalystClient(hash, class, list, loaded=None)" \
"\n" \
- "Where hash is a SHA256 fingerprint of the studied binary and list is a list of" \
+ "Where *hash* is a SHA256 fingerprint of the studied binary, *class* refers to" \
+ " the nature description of the loaded content (as provided from" \
+ " pychrysalide.analysis.LoadedContent.content_class), *list* is a list of" \
" pychrysalide.analysis.db.DbCollection instances ; this kind of list can be" \
" retrived with the pychrysalide.analysis.LoadedBinary.collections attribute." \
+ " The *loaded* object is an optional local already loaded content which has to" \
+ " be a pychrysalide.analysis.LoadedContent instance or *None*." \
"\n" \
"AnalystClient instances emit the following signals:\n" \
"* 'snapshots-updated'\n" \
@@ -127,13 +143,20 @@ static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObj
" Handlers are expected to have only one argument: the client managing the" \
" snapshots."
- ret = PyArg_ParseTuple(args, "sO", &hash, &list);
- if (!ret) return NULL;
+ loaded = NULL;
+
+ ret = PyArg_ParseTuple(args, "ssO|O&", &hash, &class, &list, convert_to_loaded_content, &loaded);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
if (!PySequence_Check(list))
{
PyErr_SetString(PyExc_TypeError, _("The second argument must be a collection list"));
- return NULL;
+ return -1;
}
length = PySequence_Length(list);
@@ -151,7 +174,7 @@ static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObj
if (ret != 1)
{
delete_collections_list(&collections);
- result = NULL;
+ result = -1;
goto exit;
}
@@ -160,14 +183,11 @@ static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObj
}
- client = g_analyst_client_new(hash, collections);
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_setup(client, hash, class, collections, loaded);
- if (client != NULL)
- {
- result = pygobject_new(G_OBJECT(client));
- g_object_unref(client);
- }
- else result = NULL;
+ result = status ? 0 : -1;
exit:
@@ -179,6 +199,50 @@ static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObj
/******************************************************************************
* *
* Paramètres : self = client à manipuler. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Envoie un contenu binaire pour conservation côté serveur. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_send_content(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à envoyer */
+ int ret; /* Bilan de lecture des args. */
+ GAnalystClient *client; /* Version native du serveur */
+ bool status; /* Bilan de l'opération */
+
+#define ANALYST_CLIENT_SEND_CONTENT_METHOD PYTHON_METHOD_DEF \
+( \
+ send_content, "$self, content, /", \
+ METH_VARARGS, py_analyst_client, \
+ "Ask the server for saving the current state of the analyzed binary" \
+ " and returns the status of the request transmission." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+ if (!ret) return NULL;
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_send_content(client, content);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
* args = arguments d'appel non utilisés ici. *
* *
* Description : Effectue une demande de sauvegarde de l'état courant. *
@@ -773,6 +837,7 @@ static int py_analyst_client_set_current_snapshot(PyObject *self, PyObject *valu
PyTypeObject *get_python_analyst_client_type(void)
{
static PyMethodDef py_analyst_client_methods[] = {
+ ANALYST_CLIENT_SEND_CONTENT_METHOD,
ANALYST_CLIENT_SAVE_METHOD,
ANALYST_CLIENT_SET_LAST_ACTIVE_METHOD,
ANALYST_CLIENT_SET_SNAPSHOT_NAME_METHOD,
@@ -802,7 +867,9 @@ PyTypeObject *get_python_analyst_client_type(void)
.tp_methods = py_analyst_client_methods,
.tp_getset = py_analyst_client_getseters,
- .tp_new = py_analyst_client_new,
+
+ .tp_init = py_analyst_client_init,
+ .tp_new = py_analyst_client_new
};
@@ -833,14 +900,17 @@ bool ensure_python_analyst_client_is_registered(void)
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
- if (!ensure_python_hub_client_is_registered())
- return false;
-
module = get_access_to_python_module("pychrysalide.analysis.db");
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ANALYST_CLIENT, type, get_python_hub_client_type()))
+ if (!ensure_python_hub_client_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ANALYST_CLIENT, type))
+ return false;
+
+ if (!define_loading_status_hint_constants(type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c
index 0cd9704..7ef658e 100644
--- a/plugins/pychrysalide/analysis/db/client.c
+++ b/plugins/pychrysalide/analysis/db/client.c
@@ -235,7 +235,7 @@ bool ensure_python_hub_client_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_HUB_CLIENT, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_HUB_CLIENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/collection.c b/plugins/pychrysalide/analysis/db/collection.c
index ca4151c..5970d15 100644
--- a/plugins/pychrysalide/analysis/db/collection.c
+++ b/plugins/pychrysalide/analysis/db/collection.c
@@ -165,7 +165,7 @@ bool ensure_python_db_collection_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DB_COLLECTION, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DB_COLLECTION, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/constants.c b/plugins/pychrysalide/analysis/db/constants.c
index 8e7765a..5e8c20d 100644
--- a/plugins/pychrysalide/analysis/db/constants.c
+++ b/plugins/pychrysalide/analysis/db/constants.c
@@ -25,6 +25,7 @@
#include "constants.h"
+#include <analysis/db/analyst.h>
#include <analysis/db/item.h>
#include <analysis/db/server.h>
@@ -152,3 +153,45 @@ bool define_hub_server_constants(PyTypeObject *type)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes pour les indications de chargement. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_loading_status_hint_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "READY", LSH_READY);
+ if (result) result = add_const_to_group(values, "ON_WAIT_LIST", LSH_ON_WAIT_LIST);
+ if (result) result = add_const_to_group(values, "NEED_CONTENT", LSH_NEED_CONTENT);
+ if (result) result = add_const_to_group(values, "NEED_FORMAT", LSH_NEED_FORMAT);
+ if (result) result = add_const_to_group(values, "NEED_ARCH", LSH_NEED_ARCH);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type_with_pyg_enum(type, false, "LoadingStatusHint", values,
+ "Indication about a loading process state.",
+ G_TYPE_LOADING_STATUS_HINT);
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/db/constants.h b/plugins/pychrysalide/analysis/db/constants.h
index 5f0afeb..ea7a0c0 100644
--- a/plugins/pychrysalide/analysis/db/constants.h
+++ b/plugins/pychrysalide/analysis/db/constants.h
@@ -39,6 +39,9 @@ bool define_db_item_constants(PyTypeObject *);
/* Définit les constantes pour les serveurs de données. */
bool define_hub_server_constants(PyTypeObject *);
+/* Définit les constantes pour les indications de chargement. */
+bool define_loading_status_hint_constants(PyTypeObject *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c
index 836f902..cc9bdf4 100644
--- a/plugins/pychrysalide/analysis/db/item.c
+++ b/plugins/pychrysalide/analysis/db/item.c
@@ -369,7 +369,7 @@ bool ensure_python_db_item_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DB_ITEM, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DB_ITEM, type))
return false;
if (!define_db_protocol_constants(type))
diff --git a/plugins/pychrysalide/analysis/db/items/Makefile.am b/plugins/pychrysalide/analysis/db/items/Makefile.am
index 80f9756..201aed7 100644
--- a/plugins/pychrysalide/analysis/db/items/Makefile.am
+++ b/plugins/pychrysalide/analysis/db/items/Makefile.am
@@ -1,22 +1,17 @@
noinst_LTLIBRARIES = libpychrysaanalysisdbitems.la
-libpychrysaanalysisdbitems_la_SOURCES = \
- bookmark.h bookmark.c \
- comment.h comment.c \
- constants.h constants.c \
- module.h module.c \
+libpychrysaanalysisdbitems_la_SOURCES = \
+ bookmark.h bookmark.c \
+ comment.h comment.c \
+ constants.h constants.c \
+ module.h module.c \
switcher.h switcher.c
-libpychrysaanalysisdbitems_la_LDFLAGS =
+libpychrysaanalysisdbitems_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysisdbitems_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/analysis/db/items/bookmark.c b/plugins/pychrysalide/analysis/db/items/bookmark.c
index af649e3..d2bc0f0 100644
--- a/plugins/pychrysalide/analysis/db/items/bookmark.c
+++ b/plugins/pychrysalide/analysis/db/items/bookmark.c
@@ -108,7 +108,7 @@ static PyObject *py_db_bookmark_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -366,7 +366,7 @@ bool ensure_python_db_bookmark_is_registered(void)
if (!ensure_python_db_item_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_DB_BOOKMARK, type, get_python_db_item_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_DB_BOOKMARK, type))
return false;
}
@@ -473,7 +473,7 @@ static PyObject *py_bookmark_collection_new(PyTypeObject *type, PyObject *args,
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -570,7 +570,7 @@ bool ensure_python_bookmark_collection_is_registered(void)
if (!ensure_python_db_collection_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_BM_COLLECTION, type, get_python_db_collection_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_BM_COLLECTION, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/items/comment.c b/plugins/pychrysalide/analysis/db/items/comment.c
index 78d4902..1358f1d 100644
--- a/plugins/pychrysalide/analysis/db/items/comment.c
+++ b/plugins/pychrysalide/analysis/db/items/comment.c
@@ -117,7 +117,7 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -464,7 +464,7 @@ bool ensure_python_db_comment_is_registered(void)
if (!ensure_python_db_item_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_DB_COMMENT, type, get_python_db_item_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_DB_COMMENT, type))
return false;
if (!define_db_comment_constants(type))
@@ -574,7 +574,7 @@ static PyObject *py_comment_collection_new(PyTypeObject *type, PyObject *args, P
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -671,7 +671,7 @@ bool ensure_python_comment_collection_is_registered(void)
if (!ensure_python_db_collection_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_COMMENT_COLLECTION, type, get_python_db_collection_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_COMMENT_COLLECTION, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/items/switcher.c b/plugins/pychrysalide/analysis/db/items/switcher.c
index 6ac5cdf..5766fe1 100644
--- a/plugins/pychrysalide/analysis/db/items/switcher.c
+++ b/plugins/pychrysalide/analysis/db/items/switcher.c
@@ -114,7 +114,7 @@ static PyObject *py_db_switcher_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -398,7 +398,7 @@ bool ensure_python_db_switcher_is_registered(void)
if (!ensure_python_db_item_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_DB_SWITCHER, type, get_python_db_item_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_DB_SWITCHER, type))
return false;
}
@@ -506,7 +506,7 @@ static PyObject *py_switcher_collection_new(PyTypeObject *type, PyObject *args,
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -603,7 +603,7 @@ bool ensure_python_switcher_collection_is_registered(void)
if (!ensure_python_db_collection_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_SWITCHER_COLLECTION, type, get_python_db_collection_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_SWITCHER_COLLECTION, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/db/server.c b/plugins/pychrysalide/analysis/db/server.c
index 9e4ee61..dae7b29 100644
--- a/plugins/pychrysalide/analysis/db/server.c
+++ b/plugins/pychrysalide/analysis/db/server.c
@@ -274,7 +274,7 @@ bool ensure_python_hub_server_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_HUB_SERVER, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_HUB_SERVER, type))
return false;
if (!define_hub_server_constants(type))
diff --git a/plugins/pychrysalide/analysis/disass/Makefile.am b/plugins/pychrysalide/analysis/disass/Makefile.am
index 0dacc15..0daa930 100644
--- a/plugins/pychrysalide/analysis/disass/Makefile.am
+++ b/plugins/pychrysalide/analysis/disass/Makefile.am
@@ -1,21 +1,14 @@
noinst_LTLIBRARIES = libpychrysaanalysisdisass.la
-libpychrysaanalysisdisass_la_SOURCES = \
- block.h block.c \
+libpychrysaanalysisdisass_la_SOURCES = \
+ block.h block.c \
module.h module.c
-libpychrysaanalysisdisass_la_LDFLAGS =
+libpychrysaanalysisdisass_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysisdisass_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/analysis/disass/block.c b/plugins/pychrysalide/analysis/disass/block.c
index 38e65a1..d82e3e2 100644
--- a/plugins/pychrysalide/analysis/disass/block.c
+++ b/plugins/pychrysalide/analysis/disass/block.c
@@ -159,7 +159,10 @@ bool ensure_python_basic_block_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BASIC_BLOCK, type, get_python_code_block_type()))
+ if (!ensure_python_code_block_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_BASIC_BLOCK, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c
index 3ed51d5..a2bf13f 100644
--- a/plugins/pychrysalide/analysis/loaded.c
+++ b/plugins/pychrysalide/analysis/loaded.c
@@ -35,6 +35,7 @@
#include <analysis/loaded-int.h>
#include <core/global.h>
+#include <plugins/dt.h>
#include "content.h"
@@ -47,14 +48,17 @@
/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Procède à l'initialisation de l'interface de génération. */
-static void py_loaded_content_interface_init(GLoadedContentIface *, gpointer *);
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_loaded_content_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise la classe générique des contenus chargés. */
+static void py_loaded_content_init_gclass(GLoadedContentClass *, gpointer);
/* Fournit le contenu représenté de l'élément chargé. */
static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *);
-/* Fournit le format associé à l'élément chargé. */
-static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *);
+/* Décrit la nature du contenu reconnu pour l'élément chargé. */
+static char *py_loaded_content_get_content_class_wrapper(const GLoadedContent *, bool);
/* Lance l'analyse propre à l'élément chargé. */
static bool py_loaded_content_analyze_wrapper(GLoadedContent *, bool, bool, wgroup_id_t, GtkStatusStack *);
@@ -62,6 +66,8 @@ static bool py_loaded_content_analyze_wrapper(GLoadedContent *, bool, bool, wgro
/* Fournit le désignation associée à l'élément chargé. */
static char *py_loaded_content_describe_wrapper(const GLoadedContent *, bool);
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Détermine le nombre de vues disponibles pour un contenu. */
static unsigned int py_loaded_content_count_views_wrapper(const GLoadedContent *);
@@ -77,6 +83,8 @@ static GtkWidget *py_loaded_content_build_view_wrapper(GLoadedContent *, unsigne
/* Retrouve l'indice correspondant à la vue donnée d'un contenu. */
static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *, GtkWidget *);
+#endif
+
/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
@@ -94,6 +102,8 @@ static PyObject *py_loaded_content_describe(PyObject *, PyObject *);
/* Etablit une liste d'obscurcissements présents. */
static PyObject *py_loaded_content_detect_obfuscators(PyObject *, PyObject *);
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Détermine le nombre de vues disponibles pour un contenu. */
static PyObject *py_loaded_content_count_views(PyObject *, PyObject *);
@@ -106,11 +116,16 @@ static PyObject *py_loaded_content_build_default_view(PyObject *, PyObject *);
/* Met en place la vue initiale pour un contenu chargé. */
static PyObject *py_loaded_content_build_view(PyObject *, PyObject *);
+#endif
+
/* Fournit le contenu représenté de l'élément chargé. */
static PyObject *py_loaded_content_get_content(PyObject *, void *);
-/* Fournit le format associé à l'élément chargé. */
-static PyObject *py_loaded_content_get_format_name(PyObject *, void *);
+/* Décrit la nature du contenu reconnu pour l'élément chargé. */
+static PyObject *py_loaded_content_get_content_class(PyObject *, void *);
+
+/* Décrit la nature du contenu reconnu pour l'élément chargé. */
+static PyObject *py_loaded_content_get_content_class_for_human(PyObject *, void *);
@@ -121,21 +136,28 @@ static PyObject *py_loaded_content_get_format_name(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : iface = interface GLib à initialiser. *
-* unused = adresse non utilisée ici. *
+* Paramètres : type = type du nouvel objet à mettre en place. *
+* args = éventuelle liste d'arguments. *
+* kwds = éventuel dictionnaire de valeurs mises à disposition. *
* *
-* Description : Procède à l'initialisation de l'interface de génération. *
+* Description : Accompagne la création d'une instance dérivée en Python. *
* *
-* Retour : - *
+* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointer *unused)
+static PyObject *py_loaded_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
+ PyObject *result; /* Objet à retourner */
+ PyTypeObject *base; /* Type de base à dériver */
+ bool first_time; /* Evite les multiples passages*/
+ GType gtype; /* Nouveau type de processeur */
+ bool status; /* Bilan d'un enregistrement */
+
#define LOADED_CONTENT_DOC \
- "The LoadedContent interface is an intermediary level of abstraction" \
+ "The LoadedContent object is an intermediary level of abstraction" \
" for all loaded binary contents to analyze." \
"\n" \
"No matter if the loaded content comes from an ELF file or XML data," \
@@ -148,7 +170,7 @@ static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointe
"\n" \
"The following methods have to be defined for new implementations:\n" \
"* pychrysalide.analysis.storage.LoadedContent._get_content();\n" \
- "* pychrysalide.analysis.storage.LoadedContent._get_format_name();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._get_content_class();\n" \
"* pychrysalide.analysis.storage.LoadedContent._analyze();\n" \
"* pychrysalide.analysis.storage.LoadedContent._describe();\n" \
"* pychrysalide.analysis.storage.LoadedContent._count_views();\n" \
@@ -157,18 +179,76 @@ static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointe
"* pychrysalide.analysis.storage.LoadedContent._build_view();\n" \
"* pychrysalide.analysis.storage.LoadedContent._get_view_index();\n"
- iface->get_content = py_loaded_content_get_content_wrapper;
- iface->get_format_name = py_loaded_content_get_format_name_wrapper;
+ /* Validations diverses */
+
+ base = get_python_loaded_content_type();
+
+ if (type == base)
+ {
+ result = NULL;
+ PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+ goto exit;
+ }
- iface->analyze = py_loaded_content_analyze_wrapper;
+ /* Mise en place d'un type dédié */
- iface->describe = py_loaded_content_describe_wrapper;
+ first_time = (g_type_from_name(type->tp_name) == 0);
- iface->count_views = py_loaded_content_count_views_wrapper;
- iface->get_view_name = py_loaded_content_get_view_name_wrapper;
- iface->build_def_view = py_loaded_content_build_default_view_wrapper;
- iface->build_view = py_loaded_content_build_view_wrapper;
- iface->get_view_index = py_loaded_content_get_view_index_wrapper;
+ gtype = build_dynamic_type(G_TYPE_LOADED_CONTENT, type->tp_name,
+ (GClassInitFunc)py_loaded_content_init_gclass, NULL, NULL);
+
+ if (first_time)
+ {
+ status = register_class_for_dynamic_pygobject(gtype, type);
+
+ if (!status)
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ }
+
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe générique des contenus chargés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_loaded_content_init_gclass(GLoadedContentClass *class, gpointer unused)
+{
+ class->get_content = py_loaded_content_get_content_wrapper;
+ class->get_content_class = py_loaded_content_get_content_class_wrapper;
+
+ class->analyze = py_loaded_content_analyze_wrapper;
+
+ class->describe = py_loaded_content_describe_wrapper;
+
+#ifdef INCLUDE_GTK_SUPPORT
+ class->count_views = py_loaded_content_count_views_wrapper;
+ class->get_view_name = py_loaded_content_get_view_name_wrapper;
+ class->build_def_view = py_loaded_content_build_default_view_wrapper;
+ class->build_view = py_loaded_content_build_view_wrapper;
+ class->get_view_index = py_loaded_content_get_view_index_wrapper;
+#endif
}
@@ -234,31 +314,34 @@ static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *
/******************************************************************************
* *
* Paramètres : content = élément chargé à manipuler. *
+* human = description humaine attendue ? *
* *
-* Description : Fournit le format associé à l'élément chargé. *
+* Description : Décrit la nature du contenu reconnu pour l'élément chargé. *
* *
-* Retour : Format associé à l'élément chargé. *
+* Retour : Classe de contenu associée à l'élément chargé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *content)
+static char *py_loaded_content_get_content_class_wrapper(const GLoadedContent *content, bool human)
{
char *result; /* Contenu interne à renvoyer */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *hobj; /* Argument pour Python */
PyObject *pyret; /* Bilan de consultation */
int ret; /* Validité d'une conversion */
-#define LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER PYTHON_WRAPPER_DEF \
+#define LOADED_CONTENT_GET_CONTENT_CLASS_WRAPPER PYTHON_WRAPPER_DEF \
( \
- _get_format_name, "$self", \
+ _get_content_class, "$self, human", \
METH_VARARGS, \
- "Abstract method used to provide the aw name of the format connected" \
- " to the loaded content.\n" \
+ "Abstract method used to provide the nature of the loaded content.\n" \
"\n" \
- "The name associated to a loaded Elf binary is for instance 'elf'." \
+ "The description associated to a loaded ARM Elf binary is for instance" \
+ " 'elf-armv7', or 'Elf, ARMv7' for the human version." \
)
result = NULL;
@@ -267,9 +350,16 @@ static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *con
pyobj = pygobject_new(G_OBJECT(content));
- if (has_python_method(pyobj, "_get_format_name"))
+ if (has_python_method(pyobj, "_get_content_class"))
{
- pyret = run_python_method(pyobj, "_get_format_name", NULL);
+ args = PyTuple_New(1);
+
+ hobj = (human ? Py_True : Py_False);
+ Py_INCREF(hobj);
+
+ PyTuple_SetItem(args, 0, hobj);
+
+ pyret = run_python_method(pyobj, "_get_content_class", args);
if (pyret != NULL)
{
@@ -282,6 +372,8 @@ static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *con
}
+ Py_DECREF(args);
+
}
Py_DECREF(pyobj);
@@ -456,6 +548,9 @@ static char *py_loaded_content_describe_wrapper(const GLoadedContent *content, b
}
+#ifdef INCLUDE_GTK_SUPPORT
+
+
/******************************************************************************
* *
* Paramètres : content = contenu chargé à consulter. *
@@ -792,6 +887,9 @@ static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *con
}
+#endif
+
+
/* ---------------------------------------------------------------------------------- */
/* CONNEXION AVEC L'API DE PYTHON */
@@ -876,7 +974,6 @@ static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *ar
int connect; /* Connexion à la base ? */
int cache; /* Préparation de rendu ? */
int ret; /* Bilan de lecture des args. */
- PyThreadState *_save; /* Sauvegarde de contexte */
GLoadedContent *content; /* Version GLib de l'élément */
bool status; /* Bilan de l'opération */
@@ -911,12 +1008,8 @@ static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *ar
content = G_LOADED_CONTENT(pygobject_get(self));
- Py_UNBLOCK_THREADS;
-
status = g_loaded_content_analyze_and_wait(content, connect, cache);
- Py_BLOCK_THREADS;
-
result = status ? Py_True : Py_False;
Py_INCREF(result);
@@ -1030,6 +1123,9 @@ static PyObject *py_loaded_content_detect_obfuscators(PyObject *self, PyObject *
}
+#ifdef INCLUDE_GTK_SUPPORT
+
+
/******************************************************************************
* *
* Paramètres : self = contenu chargé à manipuler. *
@@ -1271,6 +1367,9 @@ static PyObject *py_loaded_content_get_view_index(PyObject *self, PyObject *args
}
+#endif
+
+
/******************************************************************************
* *
* Paramètres : self = objet Python concerné par l'appel. *
@@ -1314,35 +1413,77 @@ static PyObject *py_loaded_content_get_content(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Fournit le format associé à l'élément chargé. *
+* Description : Décrit la nature du contenu reconnu pour l'élément chargé. *
* *
-* Retour : Format associé à l'élément chargé. *
+* Retour : Classe de contenu associée à l'élément chargé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_loaded_content_get_format_name(PyObject *self, void *closure)
+static PyObject *py_loaded_content_get_content_class(PyObject *self, void *closure)
{
PyObject *result; /* Instance Python à retourner */
GLoadedContent *content; /* Version GLib de l'élément */
- GBinContent *bincnt; /* Contenu binaire associé */
+ char *class; /* Nature du contenu binaire */
-#define LOADED_CONTENT_FORMAT_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+#define LOADED_CONTENT_CONTENT_CLASS_ATTRIB PYTHON_GET_DEF_FULL \
( \
- format_name, py_loaded_content, \
- "Raw name of the format connected to the loaded content.\n" \
+ content_class, py_loaded_content, \
+ "Nature of the loaded content.\n" \
"\n" \
- "The name associated to a loaded Elf binary is for instance 'elf'." \
+ "The description associated to a loaded ARM Elf binary is for instance" \
+ " 'elf-armv7'." \
)
content = G_LOADED_CONTENT(pygobject_get(self));
- bincnt = g_loaded_content_get_content(content);
+ class = g_loaded_content_get_content_class(content, false);
- result = pygobject_new(G_OBJECT(bincnt));
+ result = PyUnicode_FromString(class);
- g_object_unref(G_OBJECT(bincnt));
+ free(class);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Décrit la nature du contenu reconnu pour l'élément chargé. *
+* *
+* Retour : Classe de contenu associée à l'élément chargé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_loaded_content_get_content_class_for_human(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GLoadedContent *content; /* Version GLib de l'élément */
+ char *class; /* Nature du contenu binaire */
+
+#define LOADED_CONTENT_CONTENT_CLASS_FOR_HUMAN_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ content_class_for_human, py_loaded_content, \
+ "Humain version of the nature of the loaded content.\n" \
+ "\n" \
+ "The description associated to a loaded ARM Elf binary is for instance" \
+ " ''Elf, ARMv7'." \
+)
+
+ content = G_LOADED_CONTENT(pygobject_get(self));
+
+ class = g_loaded_content_get_content_class(content, true);
+
+ result = PyUnicode_FromString(class);
+
+ free(class);
return result;
@@ -1365,29 +1506,34 @@ PyTypeObject *get_python_loaded_content_type(void)
{
static PyMethodDef py_loaded_content_methods[] = {
LOADED_CONTENT_GET_CONTENT_WRAPPER,
- LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER,
+ LOADED_CONTENT_GET_CONTENT_CLASS_WRAPPER,
LOADED_CONTENT_ANALYZE_WRAPPER,
LOADED_CONTENT_DESCRIBE_WRAPPER,
+#ifdef INCLUDE_GTK_SUPPORT
LOADED_CONTENT_COUNT_VIEWS_WRAPPER,
LOADED_CONTENT_GET_VIEW_NAME_WRAPPER,
LOADED_CONTENT_BUILD_DEFAULT_VIEW_WRAPPER,
LOADED_CONTENT_BUILD_VIEW_WRAPPER,
LOADED_CONTENT_GET_VIEW_INDEX_WRAPPER,
+#endif
LOADED_CONTENT_ANALYZE_METHOD,
LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD,
LOADED_CONTENT_DESCRIBE_METHOD,
LOADED_CONTENT_DETECT_OBFUSCATORS_METHOD,
+#ifdef INCLUDE_GTK_SUPPORT
LOADED_CONTENT_COUNT_VIEWS_METHOD,
LOADED_CONTENT_GET_VIEW_NAME_METHOD,
LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD,
LOADED_CONTENT_BUILD_VIEW_METHOD,
LOADED_CONTENT_GET_VIEW_INDEX_METHOD,
+#endif
{ NULL }
};
static PyGetSetDef py_loaded_content_getseters[] = {
LOADED_CONTENT_CONTENT_ATTRIB,
- LOADED_CONTENT_FORMAT_NAME_ATTRIB,
+ LOADED_CONTENT_CONTENT_CLASS_ATTRIB,
+ LOADED_CONTENT_CONTENT_CLASS_FOR_HUMAN_ATTRIB,
{ NULL }
};
@@ -1396,14 +1542,16 @@ PyTypeObject *get_python_loaded_content_type(void)
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "pychrysalide.analysis.LoadedContent",
- .tp_basicsize = sizeof(PyObject),
+ .tp_basicsize = sizeof(PyGObject),
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
.tp_doc = LOADED_CONTENT_DOC,
.tp_methods = py_loaded_content_methods,
- .tp_getset = py_loaded_content_getseters
+ .tp_getset = py_loaded_content_getseters,
+
+ .tp_new = py_loaded_content_new,
};
@@ -1430,14 +1578,6 @@ bool ensure_python_loaded_content_is_registered(void)
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- static GInterfaceInfo info = { /* Paramètres d'inscription */
-
- .interface_init = (GInterfaceInitFunc)py_loaded_content_interface_init,
- .interface_finalize = NULL,
- .interface_data = NULL,
-
- };
-
type = get_python_loaded_content_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
@@ -1446,10 +1586,12 @@ bool ensure_python_loaded_content_is_registered(void)
dict = PyModule_GetDict(module);
+#ifdef INCLUDE_GTK_SUPPORT
if (!ensure_python_named_widget_is_registered())
return false;
+#endif
- if (!register_interface_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type, &info))
+ if (!register_class_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/loading.c b/plugins/pychrysalide/analysis/loading.c
index dea4e31..8a60d8a 100644
--- a/plugins/pychrysalide/analysis/loading.c
+++ b/plugins/pychrysalide/analysis/loading.c
@@ -168,7 +168,7 @@ bool ensure_python_content_explorer_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_EXPLORER, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_EXPLORER, type))
return false;
}
@@ -294,7 +294,7 @@ bool ensure_python_content_resolver_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_RESOLVER, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_RESOLVER, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c
index 9632956..6b8e441 100644
--- a/plugins/pychrysalide/analysis/module.c
+++ b/plugins/pychrysalide/analysis/module.c
@@ -41,6 +41,7 @@
#include "contents/module.h"
#include "db/module.h"
#include "disass/module.h"
+#include "scan/module.h"
#include "storage/module.h"
#include "types/module.h"
#include "../helpers.h"
@@ -86,6 +87,7 @@ bool add_analysis_module(PyObject *super)
if (result) result = add_analysis_contents_module(module);
if (result) result = add_analysis_db_module(module);
if (result) result = add_analysis_disass_module(module);
+ if (result) result = add_analysis_scan_module(module);
if (result) result = add_analysis_storage_module(module);
if (result) result = add_analysis_types_module(module);
@@ -131,6 +133,7 @@ bool populate_analysis_module(void)
if (result) result = populate_analysis_contents_module();
if (result) result = populate_analysis_db_module();
if (result) result = populate_analysis_disass_module();
+ if (result) result = populate_analysis_scan_module();
if (result) result = populate_analysis_storage_module();
if (result) result = populate_analysis_types_module();
diff --git a/plugins/pychrysalide/analysis/project.c b/plugins/pychrysalide/analysis/project.c
index e66119c..b00259a 100644
--- a/plugins/pychrysalide/analysis/project.c
+++ b/plugins/pychrysalide/analysis/project.c
@@ -402,7 +402,7 @@ bool ensure_python_study_project_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_STUDY_PROJECT, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_STUDY_PROJECT, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/routine.c b/plugins/pychrysalide/analysis/routine.c
index e33ca90..535ba84 100644
--- a/plugins/pychrysalide/analysis/routine.c
+++ b/plugins/pychrysalide/analysis/routine.c
@@ -757,7 +757,7 @@ bool ensure_python_binary_routine_is_registered(void)
if (!ensure_python_binary_symbol_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_BIN_ROUTINE, type, get_python_binary_symbol_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_BIN_ROUTINE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am
new file mode 100644
index 0000000..8c9fb77
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/Makefile.am
@@ -0,0 +1,28 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscan.la
+
+libpychrysaanalysisscan_la_SOURCES = \
+ constants.h constants.c \
+ context.h context.c \
+ core.h core.c \
+ expr.h expr.c \
+ item.h item.c \
+ module.h module.c \
+ options.h options.c \
+ scanner.h scanner.c \
+ space.h space.c
+
+libpychrysaanalysisscan_la_LIBADD = \
+ exprs/libpychrysaanalysisscanexprs.la \
+ patterns/libpychrysaanalysisscanpatterns.la
+
+libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscan_la_SOURCES:%c=)
+
+
+SUBDIRS = exprs patterns
diff --git a/plugins/pychrysalide/analysis/scan/constants.c b/plugins/pychrysalide/analysis/scan/constants.c
new file mode 100644
index 0000000..d030df2
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/constants.c
@@ -0,0 +1,128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - ajout des constantes de base pour les types
+ *
+ * Copyright (C) 2020 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 "constants.h"
+
+
+#include <analysis/scan/expr.h>
+
+
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives aux expressions de scan. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_expression_value_type_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "PENDING", SRS_PENDING);
+ if (result) result = add_const_to_group(values, "REDUCED", SRS_REDUCED);
+ if (result) result = add_const_to_group(values, "WAIT_FOR_SCAN", SRS_WAIT_FOR_SCAN);
+ if (result) result = add_const_to_group(values, "UNRESOLVABLE", SRS_UNRESOLVABLE);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "ScanReductionState", values,
+ "State of a scanexpression during the reduction process.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 constante ScanReductionState. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_reduction_state(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 ScanReductionState");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > SRS_UNRESOLVABLE)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for ScanReductionState");
+ result = 0;
+ }
+
+ else
+ *((ScanReductionState *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/constants.h b/plugins/pychrysalide/analysis/scan/constants.h
new file mode 100644
index 0000000..aa6c571
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'ajout des constantes de base pour les types
+ *
+ * Copyright (C) 2020 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_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives aux expressions de scan. */
+bool define_expression_value_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante ScanReductionState. */
+int convert_to_scan_reduction_state(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c
new file mode 100644
index 0000000..9becaf7
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/context.c
@@ -0,0 +1,432 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - équivalent Python du fichier "analysis/scan/context.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "context.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/context-int.h>
+#include <analysis/scan/expr.h>
+
+#include "expr.h"
+#include "../content.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_context, G_TYPE_SCAN_CONTEXT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_context_init(PyObject *, PyObject *, PyObject *);
+
+/* Note que la phase d'analyse de contenu est terminée. */
+static PyObject *py_scan_context_mark_scan_as_done(PyObject *, PyObject *);
+
+/* Indique si une correspondance globale a pu être établie. */
+static PyObject *py_scan_context_has_match_for_rule(PyObject *, PyObject *);
+
+/* Fournit une référence au contenu principal analysé. */
+static PyObject *py_scan_context_get_content(PyObject *, void *);
+
+/* Définit le contenu principal à analyser. */
+static int py_scan_context_set_content(PyObject *, PyObject *, void *);
+
+/* Indique si la phase d'analyse de contenu est terminée. */
+static PyObject *py_scan_context_is_scan_done(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_scan_context_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_CONTEXT_DOC \
+ "A ScanContext object tracks results of a run analysis process" \
+ " against binary contents.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanContext()"
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "");
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Note que la phase d'analyse de contenu est terminée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_mark_scan_as_done(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanContext *context; /* Contexte de suivi d'analyse */
+
+#define SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD PYTHON_METHOD_DEF \
+( \
+ mark_scan_as_done, "$self", \
+ METH_NOARGS, py_scan_context, \
+ "Note that the analysis operations are finished." \
+)
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ g_scan_context_mark_scan_as_done(context);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Indique si une correspondance globale a pu être établie. *
+* *
+* Retour : Bilan final d'une analyse (False par défaut). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ const char *name; /* Désignation de règle */
+ int ret; /* Bilan de lecture des args. */
+ GScanContext *context; /* Contexte de suivi d'analyse */
+ bool matched; /* Bilan d'analyse à renvoyer */
+
+#define SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD PYTHON_METHOD_DEF \
+( \
+ has_match_for_rule, "$self, name, /", \
+ METH_VARARGS, py_scan_context, \
+ "Provide the match status for a given scan rule.\n" \
+ "\n" \
+ "The *name* argument points to the registered rule to query.\n" \
+ "\n" \
+ "The method returns the scan final status as a boolean: *True*" \
+ " in case of match, *False* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &name);
+ if (!ret) return NULL;
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ matched = g_scan_context_has_match_for_rule(context, name);
+
+ result = matched ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant une routine binaire. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Fournit une référence au contenu principal analysé. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_get_content(PyObject *self, void *closure)
+{
+ PyObject *result; /* Eléments à retourner */
+ GScanContext *context; /* Version native */
+ GBinContent *content; /* Contenu binaire à référencer*/
+
+#define SCAN_CONTEXT_CONTENT_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ content, py_scan_context, \
+ "Link to the scanned binary content.\n" \
+ "\n" \
+ "The result is a pychrysalide.analysis.BinContent for" \
+ " fully initialized context." \
+)
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+ content = g_scan_context_get_content(context);
+
+ result = pygobject_new(G_OBJECT(content));
+
+ g_object_unref(G_OBJECT(content));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = non utilisé ici. *
+* *
+* Description : Définit le contenu principal à analyser. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_context_set_content(PyObject *self, PyObject *value, void *closure)
+{
+ GScanContext *context; /* Elément à consulter */
+ int ret; /* Bilan de lecture des args. */
+ GBinContent *content; /* Contenu binaire à référencer*/
+
+ ret = PyObject_IsInstance(value, (PyObject *)get_python_binary_content_type());
+ if (!ret) return -1;
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+ content = G_BIN_CONTENT(pygobject_get(value));
+
+ // FIXME g_scan_context_set_content(context, content);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique si la phase d'analyse de contenu est terminée. *
+* *
+* Retour : True si la phase de scan est terminée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_is_scan_done(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GScanContext *context; /* Contexte de suivi d'analyse */
+ bool status; /* Bilan de consultation */
+
+#define SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB PYTHON_IS_DEF_FULL \
+( \
+ scan_done, py_scan_context, \
+ "Tell if the analysis operations are finished.\n" \
+ "\n" \
+ "The result is a boolean: *True* if the scan is marked as" \
+ " done, *False* otherwise." \
+)
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ status = g_scan_context_is_scan_done(context);
+
+ result = status ? Py_True : Py_False;
+ 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_scan_context_type(void)
+{
+ static PyMethodDef py_scan_context_methods[] = {
+ SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD,
+ SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_context_getseters[] = {
+ SCAN_CONTEXT_CONTENT_ATTRIB,
+ SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_context_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanContext",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_CONTEXT_DOC,
+
+ .tp_methods = py_scan_context_methods,
+ .tp_getset = py_scan_context_getseters,
+
+ .tp_init = py_scan_context_init,
+ .tp_new = py_scan_context_new,
+
+ };
+
+ return &py_scan_context_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....scan.ScanContext. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_context_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanContext' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_context_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_CONTEXT, 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 contexte de suivi d'analyse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_context(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_context_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 scan context");
+ break;
+
+ case 1:
+ *((GScanContext **)dst) = G_SCAN_CONTEXT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/context.h b/plugins/pychrysalide/analysis/scan/context.h
new file mode 100644
index 0000000..477205b
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/context.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour l'équivalent Python du fichier "analysis/scan/context.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_context_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanContext'. */
+bool ensure_python_scan_context_is_registered(void);
+
+/* Tente de convertir en contexte de suivi d'analyse. */
+int convert_to_scan_context(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H */
diff --git a/plugins/pychrysalide/analysis/scan/core.c b/plugins/pychrysalide/analysis/scan/core.c
new file mode 100644
index 0000000..16df9a9
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/core.c
@@ -0,0 +1,179 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - équivalent Python du fichier "analysis/scan/core.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "core.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/core.h>
+
+
+#include "patterns/modifier.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+/* Inscrit un modificateur dans la liste des disponibles. */
+static PyObject *py_scan_register_token_modifier(PyObject *, PyObject *);
+
+/* Fournit le modificateur correspondant à un nom. */
+static PyObject *py_scan_find_token_modifiers_for_name(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Inscrit un modificateur dans la liste des disponibles. *
+* *
+* Retour : Bilan des enregistrements effectués : True si nouveauté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_register_token_modifier(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ PyObject *instance; /* Instance Python fournie */
+ GScanTokenModifier *modifier; /* Version native */
+ int ret; /* Bilan de lecture des args. */
+ bool status; /* Bilan d'un enregistrement */
+
+#define SCAN_REGISTER_TOKEN_MODIFIER_METHOD PYTHON_METHOD_DEF \
+( \
+ register_token_modifier, "inst, /", \
+ METH_VARARGS, py_scan, \
+ "Register a token modifier for byte patterns to scan.\n" \
+ "\n" \
+ "This instance will be used as singleton and has to be a" \
+ " subclass of pychrysalide.analysis.scan.patterns.TokenModifier." \
+)
+
+ ret = PyArg_ParseTuple(args, "O!", get_python_scan_token_modifier_type(), &instance);
+ if (!ret) return NULL;
+
+ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(instance));
+
+ status = register_scan_token_modifier(modifier);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Fournit le modificateur correspondant à un nom. *
+* *
+* Retour : Instance du modificateur identifié ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_find_token_modifiers_for_name(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ sized_string_t name; /* Nom d'appel à rechercher */
+ Py_ssize_t len; /* Taille de ce nom */
+ int ret; /* Bilan de lecture des args. */
+ GScanTokenModifier *modifier; /* Instance mise en place */
+
+#define SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD PYTHON_METHOD_DEF \
+( \
+ find_token_modifiers_for_name, "name, /", \
+ METH_VARARGS, py_scan, \
+ "Provide the registered instance of a pattern modifier linked" \
+ " to a given *name* provided as a key string.\n" \
+ "\n" \
+ "The returned instance is an object inherited from" \
+ " pychrysalide.analysis.scan.patterns.TokenModifier or *None*" \
+ " if no instance was found for the provided name." \
+)
+
+ ret = PyArg_ParseTuple(args, "s#", &name.static_data, &len);
+ if (!ret) return NULL;
+
+ name.len = len;
+
+ modifier = find_scan_token_modifiers_for_name(&name);
+
+ if (modifier != NULL)
+ {
+ result = pygobject_new(G_OBJECT(modifier));
+ g_object_unref(G_OBJECT(modifier));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Définit une extension du module 'scan' à compléter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_scan_module_with_core_methods(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Module à recompléter */
+
+ static PyMethodDef py_core_methods[] = {
+ SCAN_REGISTER_TOKEN_MODIFIER_METHOD,
+ SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD,
+ { NULL }
+ };
+
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ result = register_python_module_methods(module, py_core_methods);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/core.h b/plugins/pychrysalide/analysis/scan/core.h
new file mode 100644
index 0000000..e283f91
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/core.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'équivalent Python du fichier "analysis/scan/core.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_CORE_CORE_H
+#define _PLUGINS_PYCHRYSALIDE_CORE_CORE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'scan' à compléter. */
+bool populate_scan_module_with_core_methods(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_CORE_CORE_H */
diff --git a/plugins/pychrysalide/analysis/scan/expr.c b/plugins/pychrysalide/analysis/scan/expr.c
new file mode 100644
index 0000000..2d8245a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/expr.c
@@ -0,0 +1,393 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.c - équivalent Python du fichier "analysis/scan/expr.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "expr.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/expr-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/glibext/comparison.h>
+
+
+#include "constants.h"
+
+
+
+/* Initialise la classe générique des expressions d'évaluation. */
+static void py_scan_expression_init_gclass(GScanExpressionClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_expression, G_TYPE_SCAN_EXPRESSION, py_scan_expression_init_gclass);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_expression_init(PyObject *, PyObject *, PyObject *);
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
+
+/* Indique l'état de réduction d'une expression. */
+static PyObject *py_scan_expression_get_state(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe générique des expressions d'évaluation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_scan_expression_init_gclass(GScanExpressionClass *class, gpointer unused)
+{
+ class->cmp_rich = py_scan_expression_compare_rich_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_scan_expression_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ ScanReductionState state; /* Etat de réduction initial */
+ int ret; /* Bilan de lecture des args. */
+ GScanExpression *expr; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "state", NULL };
+
+#define SCAN_EXPRESSION_DOC \
+ "A ScanExpression is an abstract object which defines an expression"\
+ " involved in data matching when running a scan.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object expect"\
+ " the following arguments as keyword parameters:\n" \
+ "* *state*: initial state of reduction for the expression, as a" \
+ " pychrysalide.analysis.scan.ScanExpression.ScanReductionState" \
+ " value." \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.analysis.scan.ScanExpression._cmp_rich().\n"
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, convert_to_scan_reduction_state, &state);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ expr = G_SCAN_EXPRESSION(pygobject_get(self));
+
+ if (!g_scan_expression_create(expr, state))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create scan expression."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à cnsulter pour une comparaison. *
+* other = second objet à cnsulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *item, const GScanExpression *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+#define SCAN_EXPRESSION_CMP_RICH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, other, op, /", \
+ METH_VARARGS, \
+ "Abstract method used to compare the expression against another" \
+ " one.\n" \
+ "\n" \
+ "The second *other* instance is built from the same type as *self*."\
+ " The *op* argument points to a" \
+ " pychrysalide.glibext.ComparableItem.RichCmpOperation mode" \
+ " describing the expected comparison.\n" \
+ "\n" \
+ "The result is a boolean status or *None* if the comparison" \
+ " process is undefined." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_cmp_rich"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(other)));
+ PyTuple_SetItem(args, 1, cast_with_constants_group_from_type(get_python_comparable_item_type(),
+ "RichCmpOperation", op));
+
+ pyret = run_python_method(pyobj, "_cmp_rich", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyBool_Check(pyret);
+
+ if (ret)
+ {
+ *status = (pyret == Py_True);
+ result = true;
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique l'état de réduction d'une expression. *
+* *
+* Retour : Etat courant associé à l'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_expression_get_state(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GScanExpression *expr; /* Version GLib de l'opérande */
+ ScanReductionState state; /* Etat courant de l'expression*/
+
+#define SCAN_EXPRESSION_STATE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ state, py_scan_expression, \
+ "Current state of the expression, relative to the reduction" \
+ " process, as a" \
+ " pychrysalide.analysis.scan.ScanExpression.ScanReductionState" \
+ " value." \
+)
+
+ expr = G_SCAN_EXPRESSION(pygobject_get(self));
+
+ state = g_scan_expression_get_state(expr);
+
+ result = cast_with_constants_group_from_type(get_python_scan_expression_type(), "ScanReductionState", state);
+
+ 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_scan_expression_type(void)
+{
+ static PyMethodDef py_scan_expression_methods[] = {
+ SCAN_EXPRESSION_CMP_RICH_WRAPPER,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_expression_getseters[] = {
+ SCAN_EXPRESSION_STATE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_expression_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanExpression",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_EXPRESSION_DOC,
+
+ .tp_methods = py_scan_expression_methods,
+ .tp_getset = py_scan_expression_getseters,
+
+ .tp_init = py_scan_expression_init,
+ .tp_new = py_scan_expression_new,
+
+ };
+
+ return &py_scan_expression_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanExpression'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_expression_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanExpression'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_expression_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_comparable_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_EXPRESSION, type))
+ return false;
+
+ if (!define_expression_value_type_constants(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 expression d'évaluation généraliste. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_expression(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_expression_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 match expression");
+ break;
+
+ case 1:
+ *((GScanExpression **)dst) = G_SCAN_EXPRESSION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/expr.h b/plugins/pychrysalide/analysis/scan/expr.h
new file mode 100644
index 0000000..42f5350
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/expr.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.h - prototypes pour l'équivalent Python du fichier "analysis/scan/expr.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_expression_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanExpression'. */
+bool ensure_python_scan_expression_is_registered(void);
+
+/* Tente de convertir en expression d'évaluation généraliste. */
+int convert_to_scan_expression(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/Makefile.am b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am
new file mode 100644
index 0000000..e40d4de
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanexprs.la
+
+libpychrysaanalysisscanexprs_la_SOURCES = \
+ constants.h constants.c \
+ literal.h literal.c \
+ module.h module.c
+
+libpychrysaanalysisscanexprs_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanexprs_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.c b/plugins/pychrysalide/analysis/scan/exprs/constants.c
new file mode 100644
index 0000000..b11ac4c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/constants.c
@@ -0,0 +1,128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - ajout des constantes de base pour les expressions
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "constants.h"
+
+
+#include <analysis/scan/exprs/literal.h>
+
+
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives aux expressions de scan. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_literal_expression_value_type_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "LVT_BOOLEAN", LVT_BOOLEAN);
+ if (result) result = add_const_to_group(values, "SIGNED_INTEGER", LVT_SIGNED_INTEGER);
+ if (result) result = add_const_to_group(values, "UNSIGNED_INTEGER", LVT_UNSIGNED_INTEGER);
+ if (result) result = add_const_to_group(values, "STRING", LVT_STRING);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "LiteralValueType", values,
+ "Type of value carried by a literal scan expression.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 constante LiteralValueType. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_literal_expression_value_type(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 LiteralValueType");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > LVT_REG_EXPR)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for LiteralValueType");
+ result = 0;
+ }
+
+ else
+ *((LiteralValueType *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.h b/plugins/pychrysalide/analysis/scan/exprs/constants.h
new file mode 100644
index 0000000..e5b8e8c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'ajout des constantes de base pour les expressions
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives aux expressions litérales. */
+bool define_literal_expression_value_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante LiteralValueType. */
+int convert_to_literal_expression_value_type(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.c b/plugins/pychrysalide/analysis/scan/exprs/literal.c
new file mode 100644
index 0000000..d7ae002
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/literal.c
@@ -0,0 +1,281 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.c - équivalent Python du fichier "analysis/scan/exprs/literal.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "literal.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/exprs/literal-int.h>
+
+
+#include "constants.h"
+#include "../expr.h"
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_literal_expression, G_TYPE_SCAN_LITERAL_EXPRESSION);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_literal_expression_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_literal_expression_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_value; /* Valeur en version Python */
+ int ret; /* Bilan de lecture des args. */
+ LiteralValueType vtype; /* Valeur à porter */
+ bool arg_boolean; /* Argument natif booléen */
+ unsigned long long arg_uinteger; /* Argument natif entier */
+ sized_string_t arg_string; /* Argument natif textuel */
+ Py_ssize_t arg_str_length; /* Taille de ce texte */
+ void *arg_ptr; /* Pointeur vers un argument */
+ GScanLiteralExpression *expr; /* Création GLib à transmettre */
+
+#define SCAN_LITERAL_EXPRESSION_DOC \
+ "A ScanLiteralExpression object defines expression carrying" \
+ " literal values available for scan match conditions.\n" \
+ "\n" \
+ "Instances can be created using one of the following" \
+ " constructors:\n" \
+ "\n" \
+ " ScanLiteralExpression(value)" \
+ "\n" \
+ "\n" \
+ "Where *value* is either a boolean, an integer or bytes."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O", &py_value);
+ if (!ret) return -1;
+
+ if (PyBool_Check(py_value))
+ {
+ vtype = LVT_BOOLEAN;
+
+ arg_boolean = (py_value == Py_True);
+ arg_ptr = &arg_boolean;
+
+ }
+
+ else if (PyLong_Check(py_value))
+ {
+ if (1 /* sign - TODO */)
+ ;
+
+ vtype = LVT_UNSIGNED_INTEGER;
+
+ arg_uinteger = PyLong_AsUnsignedLongLong(py_value);
+ arg_ptr = &arg_uinteger;
+
+ }
+
+ else if (PyBytes_Check(py_value))
+ {
+ vtype = LVT_STRING;
+
+ ret = PyBytes_AsStringAndSize(py_value, &arg_string.data, &arg_str_length);
+ if (ret == -1) return -1;
+
+ arg_string.len = arg_str_length;
+ arg_ptr = &arg_string;
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unsupported Python value for a literal scan expression."));
+ return -1;
+ }
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ expr = G_SCAN_LITERAL_EXPRESSION(pygobject_get(self));
+
+ if (!g_scan_literal_expression_create(expr, vtype, arg_ptr))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create literal expression."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_literal_expression_type(void)
+{
+ static PyMethodDef py_scan_literal_expression_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_literal_expression_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_literal_expression_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.exprs.ScanLiteralExpression",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_LITERAL_EXPRESSION_DOC,
+
+ .tp_methods = py_scan_literal_expression_methods,
+ .tp_getset = py_scan_literal_expression_getseters,
+
+ .tp_init = py_scan_literal_expression_init,
+ .tp_new = py_scan_literal_expression_new,
+
+ };
+
+ return &py_scan_literal_expression_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....PlainModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_literal_expression_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'PlainModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_literal_expression_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.exprs");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_expression_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_LITERAL_EXPRESSION, type))
+ return false;
+
+ if (!define_literal_expression_value_type_constants(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 transmission d'octets à l'identique. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_literal_expression(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_literal_expression_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 scan literal expression");
+ break;
+
+ case 1:
+ *((GScanLiteralExpression **)dst) = G_SCAN_LITERAL_EXPRESSION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.h b/plugins/pychrysalide/analysis/scan/exprs/literal.h
new file mode 100644
index 0000000..8e7ea70
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/literal.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.h - équivalent Python du fichier "analysis/scan/exprs/literal.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_literal_expression_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.exprs.ScanLiteralExpression'. */
+bool ensure_python_scan_literal_expression_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_literal_expression(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.c b/plugins/pychrysalide/analysis/scan/exprs/module.c
new file mode 100644
index 0000000..4f38430
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/module.c
@@ -0,0 +1,103 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire exprs en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "literal.h"
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis....modifiers' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_exprs_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC \
+ "This module provide expressions used to build a match condition."
+
+ static PyModuleDef py_chrysalide_analysis_scan_exprs_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.exprs",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_exprs_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis...patterns.modifiers'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_exprs_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_literal_expression_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.h b/plugins/pychrysalide/analysis/scan/exprs/module.h
new file mode 100644
index 0000000..ee4b8ab
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire exprs en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.exprs' à un module Python. */
+bool add_analysis_scan_exprs_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.exprs'. */
+bool populate_analysis_scan_exprs_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c
new file mode 100644
index 0000000..014ae24
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/item.c
@@ -0,0 +1,740 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - équivalent Python du fichier "analysis/scan/item.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "item.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/item-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "context.h"
+
+
+
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Initialise la classe des éléments appelables enregistrés. */
+static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_registered_item, G_TYPE_SCAN_REGISTERED_ITEM, py_scan_registered_item_init_gclass);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_registered_item_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue un appel à une fonction enregistrée. */
+static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
+/* Lance une résolution d'élément à appeler. */
+static PyObject *py_scan_registered_item_resolve(PyObject *, PyObject *);
+
+/* Fournit le désignation associée à un composant nommé. */
+static PyObject *py_scan_registered_item_get_name(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe des éléments appelables enregistrés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *class, gpointer unused)
+{
+ class->get_name = py_scan_registered_item_get_name_wrapper;
+ class->resolve = py_scan_registered_item_resolve_wrapper;
+ class->reduce = py_scan_registered_item_reduce_wrapper;
+ class->run_call = py_scan_registered_item_run_call_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_scan_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_REGISTERED_ITEM_DOC \
+ "The *RegisteredItem* class is an abstract definition which is" \
+ " the base for all keywords involved in a match condition" \
+ " expression.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object" \
+ " expect no particular argument.\n" \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._resolve();\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._reduce();\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._call().\n" \
+ "\n" \
+ "One item has to be defined as class attributes in the final" \
+ " class:\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._name.\n"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *item)
+{
+ char *result; /* Désignation à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyname; /* Nom en objet Python */
+ int ret; /* Bilan d'une conversion */
+
+#define SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF \
+( \
+ _name, \
+ "Provide the keyword of the expression item to be evaluated.\n" \
+ "\n" \
+ "The result has to be a string." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (PyObject_HasAttrString(pyobj, "_name"))
+ {
+ pyname = PyObject_GetAttrString(pyobj, "_name");
+
+ if (pyname != NULL)
+ {
+ ret = PyUnicode_Check(pyname);
+
+ if (ret)
+ result = strdup(PyUnicode_AsUTF8(pyname));
+
+ Py_DECREF(pyname);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, target, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to resolve an item by name.\n" \
+ "\n" \
+ "The *target* argument provide the name of the searched item;" \
+ " *ctx* is a pychrysalide.analysis.scan.ScanContext instance" \
+ " providing information about the current state; *scope* is a" \
+ " pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.RegisteredItem" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_resolve"))
+ {
+ args = PyTuple_New(3);
+ PyTuple_SetItem(args, 0, PyUnicode_FromString(target));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_resolve", args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_SCAN_REGISTERED_ITEM(gobj_ret))
+ {
+ *out = G_SCAN_REGISTERED_ITEM(gobj_ret);
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define SCAN_REGISTERED_ITEM_REDUCE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to replace the item by an equivalent reduced" \
+ " value.\n" \
+ "\n" \
+ "The *ctx* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance providing information about the current state; *scope*" \
+ " is a pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.ScanExpression" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_reduce"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_reduce", args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_SCAN_EXPRESSION(gobj_ret))
+ {
+ *out = G_SCAN_EXPRESSION(gobj_ret);
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Effectue un appel à une fonction enregistrée. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *sub_args; /* Sous-arguments pour l'appel */
+ size_t i; /* Boucle de parcours */
+ PyObject *py_args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define SCAN_REGISTERED_ITEM_CALL_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, args, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to replace the item and its arguments by an" \
+ " equivalent reduced value.\n" \
+ "\n" \
+ "The *args* argument is a tuple of already reduced" \
+ " pychrysalide.analysis.scan.ScanExpression objects; ctx* argument" \
+ " is a pychrysalide.analysis.scan.ScanContext instance providing" \
+ " information about the current state; *scope* is a" \
+ " pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.ScanExpression" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_call"))
+ {
+ sub_args = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(sub_args, 1, pygobject_new(G_OBJECT(args[i])));
+
+ py_args = PyTuple_New(3);
+ PyTuple_SetItem(py_args, 0, sub_args);
+ PyTuple_SetItem(py_args, 1, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(py_args, 2, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_call", py_args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_OBJECT(gobj_ret))
+ {
+ *out = gobj_ret;
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(py_args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = élément d'appel à consulter. *
+* args = arguments fournis pour l'opération. *
+* *
+* Description : Lance une résolution d'élément à appeler. *
+* *
+* Retour : Nouvel élément d'appel identifié ou None. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_registered_item_resolve(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ const char *target; /* Désignation de la cible */
+ GScanContext *ctx; /* Contexte d'analyse */
+ GScanScope *scope; /* Portée de variables locales */
+ int ret; /* Bilan de lecture des args. */
+ GScanRegisteredItem *item; /* Version native */
+ bool status; /* Bilan d'exécution */
+ GScanRegisteredItem *resolved; /* Elément trouvé */
+
+#define SCAN_REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF \
+( \
+ resolve, "$self, target, /, ctx=None, scope=None", \
+ METH_VARARGS, py_scan_registered_item, \
+ "Resolve a name into a scan item." \
+ "\n" \
+ "The *target* name is the only mandatory parameter and has to point"\
+ " to only one item. The *ctx* argument points to an optional useful"\
+ " storage for resolution lookup, as a" \
+ " pychrysalide.analysis.scan.ScanContext instance. The *args* list" \
+ " defines an optional list of arguments, as" \
+ " pychrysalide.analysis.scan.ScanExpression instances, to use for" \
+ " building the resolved item. The *final* flag states if the" \
+ " scanning process is about to conclude or not." \
+ "\n" \
+ "The result is an object inheriting from" \
+ " pychrysalide.analysis.scan.RegisteredItem or *None* if the" \
+ " resolution operation failed." \
+)
+
+ ctx = NULL;
+ scope = NULL;
+
+ ret = PyArg_ParseTuple(args, "s|O&", &target,
+ convert_to_scan_context, &ctx);
+ if (!ret) return NULL;
+
+ item = G_SCAN_REGISTERED_ITEM(pygobject_get(self));
+
+ status = g_scan_registered_item_resolve(item, target, ctx, scope, &resolved);
+
+ if (!status)
+ {
+ result = NULL;
+ PyErr_Format(PyExc_RuntimeError, _("Unable to resolve any target from the item"));
+ }
+ else
+ {
+ if (resolved != NULL)
+ {
+ result = pygobject_new(G_OBJECT(resolved));
+ g_object_unref(G_OBJECT(resolved));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un composant nommé à manipuler.*
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le désignation associée à un composant nommé. *
+* *
+* Retour : Description courante. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_registered_item_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Décompte à retourner */
+ GScanRegisteredItem *item; /* Version native */
+ char *name; /* Désignation à convertir */
+
+#define SCAN_REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_scan_registered_item, \
+ "Name linked to the registered item.\n" \
+ "\n" \
+ "The result should be a string, or *None* for the root namespace." \
+)
+
+ item = G_SCAN_REGISTERED_ITEM(pygobject_get(self));
+
+ name = g_scan_registered_item_get_name(item);
+
+ if (name == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = PyUnicode_FromString(name);
+ free(name);
+ }
+
+ 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_scan_registered_item_type(void)
+{
+ static PyMethodDef py_scan_registered_item_methods[] = {
+ SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER,
+ SCAN_REGISTERED_ITEM_REDUCE_WRAPPER,
+ SCAN_REGISTERED_ITEM_CALL_WRAPPER,
+ SCAN_REGISTERED_ITEM_RESOLVE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_registered_item_getseters[] = {
+ SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER,
+ SCAN_REGISTERED_ITEM_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_registered_item_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanRegisteredItem",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_REGISTERED_ITEM_DOC,
+
+ .tp_methods = py_scan_registered_item_methods,
+ .tp_getset = py_scan_registered_item_getseters,
+
+ .tp_init = py_scan_registered_item_init,
+ .tp_new = py_scan_registered_item_new,
+
+ };
+
+ return &py_scan_registered_item_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...ScanRegisteredItem'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_registered_item_is_registered(void)
+{
+ PyTypeObject *type; /* Type 'ScanRegisteredItem' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_registered_item_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REGISTERED_ITEM, 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 expression d'évaluation généraliste. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_registered_item(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_registered_item_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 generic scan expression");
+ break;
+
+ case 1:
+ *((GScanRegisteredItem **)dst) = G_SCAN_REGISTERED_ITEM(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/item.h b/plugins/pychrysalide/analysis/scan/item.h
new file mode 100644
index 0000000..773908c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/item.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour l'équivalent Python du fichier "analysis/scan/item.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_registered_item_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanRegisteredItem'. */
+bool ensure_python_scan_registered_item_is_registered(void);
+
+/* Tente de convertir en expression d'évaluation généraliste. */
+int convert_to_scan_registered_item(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H */
diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c
new file mode 100644
index 0000000..9ae0e52
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/module.c
@@ -0,0 +1,125 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire scan en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "context.h"
+#include "core.h"
+#include "expr.h"
+#include "item.h"
+#include "options.h"
+#include "scanner.h"
+#include "space.h"
+#include "exprs/module.h"
+#include "patterns/module.h"
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.scan' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_module);
+
+ result = (module != NULL);
+
+ if (result) result = add_analysis_scan_exprs_module(module);
+ if (result) result = add_analysis_scan_patterns_module(module);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis.scan'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_content_scanner_is_registered();
+ if (result) result = ensure_python_scan_context_is_registered();
+ if (result) result = ensure_python_scan_expression_is_registered();
+ if (result) result = ensure_python_scan_registered_item_is_registered();
+ if (result) result = ensure_python_scan_options_is_registered();
+ if (result) result = ensure_python_scan_namespace_is_registered();
+
+ if (result) result = populate_scan_module_with_core_methods();
+
+ if (result) result = populate_analysis_scan_exprs_module();
+ if (result) result = populate_analysis_scan_patterns_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/module.h b/plugins/pychrysalide/analysis/scan/module.h
new file mode 100644
index 0000000..a5e84b5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire scan en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan' à un module Python. */
+bool add_analysis_scan_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan'. */
+bool populate_analysis_scan_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/options.c b/plugins/pychrysalide/analysis/scan/options.c
new file mode 100644
index 0000000..84c1784
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/options.c
@@ -0,0 +1,511 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.c - équivalent Python du fichier "analysis/scan/options.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "options.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/options-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_options, G_TYPE_SCAN_OPTIONS);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_options_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le type d'un moteur d'analyse de données sélectionné. */
+static PyObject *py_scan_options_get_backend_for_data(PyObject *, void *);
+
+/* Sélectionne un type de moteur d'analyse pour données brutes. */
+static int py_scan_options_set_backend_for_data(PyObject *, PyObject *, void *);
+
+/* Impose le format JSON comme type de sortie. */
+static PyObject *py_scan_options_get_print_json(PyObject *, void *);
+
+/* Mémorise le format JSON comme type de sortie. */
+static int py_scan_options_set_print_json(PyObject *, PyObject *, void *);
+
+/* Indique un besoin d'affichage des correspondances finales. */
+static PyObject *py_scan_options_get_print_strings(PyObject *, void *);
+
+/* Mémorise un besoin d'affichage des correspondances finales. */
+static int py_scan_options_set_print_strings(PyObject *, PyObject *, void *);
+
+/* Indique un besoin de statistiques en fin de compilation. */
+static PyObject *py_scan_options_get_print_stats(PyObject *, void *);
+
+/* Mémorise un besoin de statistiques en fin de compilation. */
+static int py_scan_options_set_print_stats(PyObject *, 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_scan_options_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_OPTIONS_DOC \
+ "The *ScanOptions* class stores all parameters used to tune" \
+ " a scanning process.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanOptions()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique le type d'un moteur d'analyse de données sélectionné.*
+* *
+* Retour : Type d'objet, idéalement valide. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_backend_for_data(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ GType type; /* Type à transcrire */
+
+#define SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ backend_for_data, py_scan_options, \
+ "Type of the selected scan algorithm." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ type = g_scan_options_get_backend_for_data(options);
+
+ result = pyg_type_wrapper_new(type);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Sélectionne un type de moteur d'analyse pour données brutes. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_backend_for_data(PyObject *self, PyObject *value, void *closure)
+{
+ GType type; /* Type à transcrit */
+ GScanOptions *options; /* Version native */
+
+ type = pyg_type_from_object(value);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_backend_for_data(options, type);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Impose le format JSON comme type de sortie. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_json(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_JSON_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_json, py_scan_options, \
+ "Define if the process summary is output into a JSON" \
+ " format at the end of the scan or not." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_json(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise le format JSON comme type de sortie. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_json(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_json(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique un besoin d'affichage des correspondances finales. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_strings(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_STRINGS_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_strings, py_scan_options, \
+ "Define if the matching patterns are printed with found" \
+ " offset at the end of the scan or not." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_strings(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise un besoin d'affichage des correspondances finales. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_strings(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_strings(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_stats(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_STATS_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_stats, py_scan_options, \
+ "Control the output of final statistics afer a scan." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_stats(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_stats(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_stats(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_options_type(void)
+{
+ static PyMethodDef py_scan_options_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_options_getseters[] = {
+ SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB,
+ SCAN_OPTIONS_PRINT_JSON_ATTRIB,
+ SCAN_OPTIONS_PRINT_STRINGS_ATTRIB,
+ SCAN_OPTIONS_PRINT_STATS_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_options_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanOptions",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = SCAN_OPTIONS_DOC,
+
+ .tp_methods = py_scan_options_methods,
+ .tp_getset = py_scan_options_getseters,
+
+ .tp_init = py_scan_options_init,
+ .tp_new = py_scan_options_new,
+
+ };
+
+ return &py_scan_options_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanOptions'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_options_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanOptions' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_options_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_OPTIONS, 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 ensemble d'options d'analyses. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_options(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_options_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 scan options");
+ break;
+
+ case 1:
+ *((GScanOptions **)dst) = G_SCAN_OPTIONS(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/options.h b/plugins/pychrysalide/analysis/scan/options.h
new file mode 100644
index 0000000..3e83880
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/options.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.h - prototypes pour l'équivalent Python du fichier "analysis/scan/options.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_options_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanOptions'. */
+bool ensure_python_scan_options_is_registered(void);
+
+/* Tente de convertir en ensemble d'options d'analyses. */
+int convert_to_scan_options(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
new file mode 100644
index 0000000..dd26fa5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
@@ -0,0 +1,22 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatterns.la
+
+libpychrysaanalysisscanpatterns_la_SOURCES = \
+ backend.h backend.c \
+ modifier.h modifier.c \
+ module.h module.c
+
+libpychrysaanalysisscanpatterns_la_LIBADD = \
+ backends/libpychrysaanalysisscanpatternsbackends.la \
+ modifiers/libpychrysaanalysisscanpatternsmodifiers.la
+
+libpychrysaanalysisscanpatterns_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatterns_la_SOURCES:%c=)
+
+
+SUBDIRS = backends modifiers
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.c b/plugins/pychrysalide/analysis/scan/patterns/backend.c
new file mode 100644
index 0000000..03db143
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backend.c
@@ -0,0 +1,202 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.c - équivalent Python du fichier "analysis/scan/backend.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "backend.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/patterns/backend-int.h>
+
+
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(engine_backend, G_TYPE_ENGINE_BACKEND, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_engine_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_engine_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define ENGINE_BACKEND_DOC \
+ "An *EngineBackend* object is the root class of all scan algorithm" \
+ " looking for data patterns."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_engine_backend_type(void)
+{
+ static PyMethodDef py_engine_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_engine_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_engine_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.EngineBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = ENGINE_BACKEND_DOC,
+
+ .tp_methods = py_engine_backend_methods,
+ .tp_getset = py_engine_backend_getseters,
+
+ .tp_init = py_engine_backend_init,
+ .tp_new = py_engine_backend_new,
+
+ };
+
+ return &py_engine_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....EngineBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_engine_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanNamespace' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_engine_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ENGINE_BACKEND, 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 méthode de recherches. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_engine_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_engine_backend_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 engine backend");
+ break;
+
+ case 1:
+ *((GEngineBackend **)dst) = G_ENGINE_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.h b/plugins/pychrysalide/analysis/scan/patterns/backend.h
new file mode 100644
index 0000000..6b1f4cd
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backend.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.h - prototypes pour l'équivalent Python du fichier "analysis/scan/backend.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_engine_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.EngineBackend'. */
+bool ensure_python_engine_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherches. */
+int convert_to_engine_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am
new file mode 100644
index 0000000..cccfc2d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsbackends.la
+
+libpychrysaanalysisscanpatternsbackends_la_SOURCES = \
+ acism.h acism.c \
+ bitap.h bitap.c \
+ module.h module.c
+
+libpychrysaanalysisscanpatternsbackends_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatternsbackends_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c
new file mode 100644
index 0000000..56d0b55
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.c - équivalent Python du fichier "analysis/scan/patterns/backends/acism.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "acism.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/backends/acism-int.h>
+
+
+#include "../backend.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(acism_backend, G_TYPE_ACISM_BACKEND);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_acism_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_acism_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define ACISM_BACKEND_DOC \
+ "A *AcismBackend* class provide an implementation of the Aho-Corasick" \
+ " search algorithm with Interleaved State-transition Matrix (ACISM)." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " AcismBackend()" \
+ "\n" \
+ "See the relative white paper for more information:" \
+ " https://docs.google.com/document/d/1e9Qbn22__togYgQ7PNyCz3YzIIVPKvrf8PCrFa74IFM"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_acism_backend_type(void)
+{
+ static PyMethodDef py_acism_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_acism_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_acism_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.backends.AcismBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = ACISM_BACKEND_DOC,
+
+ .tp_methods = py_acism_backend_methods,
+ .tp_getset = py_acism_backend_getseters,
+
+ .tp_init = py_acism_backend_init,
+ .tp_new = py_acism_backend_new,
+
+ };
+
+ return &py_acism_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....AcismBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_acism_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'AcismBackend'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_acism_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_engine_backend_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ACISM_BACKEND, 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 méthode de recherche ACISM. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_acism_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_acism_backend_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 ACISM backend");
+ break;
+
+ case 1:
+ *((GAcismBackend **)dst) = G_ACISM_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h
new file mode 100644
index 0000000..9ed61fa
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/acism.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_acism_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.AcismBackend'. */
+bool ensure_python_acism_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherche ACISM. */
+int convert_to_acism_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c
new file mode 100644
index 0000000..c910f26
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.c - équivalent Python du fichier "analysis/scan/patterns/backends/bitap.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "bitap.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/backends/bitap-int.h>
+
+
+#include "../backend.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(bitap_backend, G_TYPE_BITAP_BACKEND);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_bitap_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_bitap_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define BITAP_BACKEND_DOC \
+ "A *BitapBackend* class provide an implementation of the Bitap" \
+ " search algorithm." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " BitapBackend()" \
+ "\n" \
+ "See the relative white paper for more information:" \
+ " https://en.wikipedia.org/wiki/Bitap_algorithm"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_bitap_backend_type(void)
+{
+ static PyMethodDef py_bitap_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_bitap_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_bitap_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.backends.BitapBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = BITAP_BACKEND_DOC,
+
+ .tp_methods = py_bitap_backend_methods,
+ .tp_getset = py_bitap_backend_getseters,
+
+ .tp_init = py_bitap_backend_init,
+ .tp_new = py_bitap_backend_new,
+
+ };
+
+ return &py_bitap_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....BitapBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_bitap_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'BitapBackend'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_bitap_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_engine_backend_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_BITAP_BACKEND, 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 méthode de recherche BITAP. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_bitap_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_bitap_backend_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 Bitap backend");
+ break;
+
+ case 1:
+ *((GBitapBackend **)dst) = G_BITAP_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h
new file mode 100644
index 0000000..f7853d4
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/bitap.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_bitap_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.BitapBackend'. */
+bool ensure_python_bitap_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherche Bitap. */
+int convert_to_bitap_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.c b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c
new file mode 100644
index 0000000..f4a0293
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c
@@ -0,0 +1,106 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire backends en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "acism.h"
+#include "bitap.h"
+#include "../../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.....backends' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_backends_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_backends_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns.backends",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_backends_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis....patterns.backends'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_backends_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_acism_backend_is_registered();
+ if (result) result = ensure_python_bitap_backend_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.h b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h
new file mode 100644
index 0000000..ab1aad5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire backends en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns.backends' à un module Python. */
+bool add_analysis_scan_patterns_backends_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns.backends'. */
+bool populate_analysis_scan_patterns_backends_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.c b/plugins/pychrysalide/analysis/scan/patterns/modifier.c
new file mode 100644
index 0000000..6547d91
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.c
@@ -0,0 +1,416 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.c - équivalent Python du fichier "analysis/scan/modifier.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "modifier.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_token_modifier, G_TYPE_SCAN_TOKEN_MODIFIER, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_token_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_token_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_TOKEN_MODIFIER_DOC \
+ "An *TokenModifier* object is the root class of all modifiers" \
+ " for byte patterns."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = tampon de données à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Liste des nouvelle(s) séquence(s) d'octets obtenue(s). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_token_modifier_transform(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ PyObject *py_src; /* Motifs Python en entrée */
+ PyObject *py_arg; /* Eventuel paramètre de config*/
+ sized_binary_t src; /* Entrée au format adapté */
+ Py_ssize_t len; /* Quantité de ces données */
+ int ret; /* Bilan de lecture des args. */
+ sized_binary_t *src_list; /* Entrées au format adapté */
+ size_t scount; /* Taille de cette liste */
+ bool dyn_src; /* Allocation dynamique ? */
+ Py_ssize_t size; /* Taille d'une séquence */
+ Py_ssize_t k; /* Boucle de parcours #1 */
+ PyObject *item; /* Elément de liste de motifs */
+ modifier_arg_t arg; /* Eventuelle précision */
+ GScanTokenModifier *modifier; /* Version native de l'instance*/
+ sized_binary_t *dest; /* Liste des nouvelles chaînes */
+ size_t dcount; /* Taille de cette liste */
+ bool status; /* Bilan de l'opération */
+ size_t i; /* Boucle de parcours #2 */
+
+#define SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD PYTHON_METHOD_DEF \
+( \
+ transform, "$self, data, /, arg", \
+ METH_VARARGS, py_scan_token_modifier, \
+ "Transform data from a byte pattern for an incoming scan.\n" \
+ "\n" \
+ "The data has to be provided as bytes.\n" \
+ "\n" \
+ "The method returns a tuple of transformed data as bytes, or" \
+ " *None* in case of error." \
+)
+
+ py_arg = NULL;
+
+ ret = PyArg_ParseTuple(args, "O|O", &py_src, &py_arg);
+ if (!ret) return NULL;
+
+ /* Constitution des motifs d'entrée */
+
+ if (PyBytes_Check(py_src))
+ {
+ ret = PyBytes_AsStringAndSize(py_src, &src.data, &len);
+ if (ret == -1) return NULL;
+
+ src.len = len;
+
+ src_list = &src;
+ scount = 1;
+
+ dyn_src = false;
+
+ }
+
+ else if (PySequence_Check(py_src))
+ {
+ size = PySequence_Size(py_src);
+
+ src_list = malloc(size * sizeof(sized_binary_t));
+ scount = size;
+
+ dyn_src = true;
+
+ for (k = 0; k < size; k++)
+ {
+ item = PySequence_ITEM(py_src, k);
+
+ if (PyBytes_Check(item))
+ {
+ ret = PyBytes_AsStringAndSize(item, &src_list[k].data, &len);
+ if (ret == -1) return NULL;
+
+ src_list[k].len = len;
+
+ }
+ else
+ {
+ free(src_list);
+
+ PyErr_SetString(PyExc_TypeError, "lists of items other than bytes are not supported");
+ return NULL;
+ }
+
+ }
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "only bytes and lists of bytes are expected as input for modifiers");
+ return NULL;
+ }
+
+ /* Récupération d'une éventuelle précision opérationnelle */
+
+ if (py_arg != NULL)
+ {
+ if (PyLong_Check(py_arg))
+ {
+ arg.type = MAT_UNSIGNED_INTEGER;
+ arg.value.u_integer = PyLong_AsUnsignedLongLong(py_arg);
+ }
+
+ else
+ {
+ if (dyn_src)
+ free(src_list);
+
+ PyErr_SetString(PyExc_TypeError, "unable to handle the argument type for calling a modifier");
+ return NULL;
+
+ }
+
+ }
+
+ /* Création des nouveaux motifs */
+
+ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self));
+
+ if (py_arg == NULL)
+ status = g_scan_token_modifier_transform(modifier, src_list, scount, &dest, &dcount);
+ else
+ status = g_scan_token_modifier_transform_with_arg(modifier, src_list, scount, &arg, &dest, &dcount);
+
+ if (dyn_src)
+ free(src_list);
+
+ if (status)
+ {
+ result = PyTuple_New(dcount);
+
+ for (i = 0; i < dcount; i++)
+ {
+ PyTuple_SetItem(result, i, PyBytes_FromStringAndSize(dest[i].data, dest[i].len));
+ exit_szstr(&dest[i]);
+ }
+
+ free(dest);
+
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un composant nommé à manipuler.*
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le désignation associée à un composant nommé. *
+* *
+* Retour : Description courante. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_token_modifier_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Décompte à retourner */
+ GScanTokenModifier *modifier; /* Version native */
+ char *name; /* Désignation à convertir */
+
+#define SCAN_TOKEN_MODIFIER_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_scan_token_modifier, \
+ "Call name for the modifier.\n" \
+ "\n" \
+ "The result is a string." \
+)
+
+ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self));
+
+ name = g_scan_token_modifier_get_name(modifier);
+
+ if (name == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = PyUnicode_FromString(name);
+ free(name);
+ }
+
+ 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_scan_token_modifier_type(void)
+{
+ static PyMethodDef py_scan_token_modifier_methods[] = {
+ SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_token_modifier_getseters[] = {
+ SCAN_TOKEN_MODIFIER_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_token_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.TokenModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_TOKEN_MODIFIER_DOC,
+
+ .tp_methods = py_scan_token_modifier_methods,
+ .tp_getset = py_scan_token_modifier_getseters,
+
+ .tp_init = py_scan_token_modifier_init,
+ .tp_new = py_scan_token_modifier_new,
+
+ };
+
+ return &py_scan_token_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....TokenModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_token_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'TokenModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_token_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_TOKEN_MODIFIER, 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 transformation de séquence d'octets. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_token_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_token_modifier_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 token modifier");
+ break;
+
+ case 1:
+ *((GScanTokenModifier **)dst) = G_SCAN_TOKEN_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.h b/plugins/pychrysalide/analysis/scan/patterns/modifier.h
new file mode 100644
index 0000000..770b2c1
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.h - prototypes pour l'équivalent Python du fichier "analysis/scan/modifier.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_token_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.TokenModifier'. */
+bool ensure_python_scan_token_modifier_is_registered(void);
+
+/* Tente de convertir en transformation de séquence d'octets. */
+int convert_to_scan_token_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
new file mode 100644
index 0000000..ae53e45
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsmodifiers.la
+
+libpychrysaanalysisscanpatternsmodifiers_la_SOURCES = \
+ hex.h hex.c \
+ list.h list.c \
+ module.h module.c \
+ plain.h plain.c \
+ rev.h rev.c \
+ xor.h xor.c
+
+libpychrysaanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatternsmodifiers_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
new file mode 100644
index 0000000..503580d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "hex.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/hex.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_hex_modifier, G_TYPE_SCAN_HEX_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_hex_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_hex_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_HEX_MODIFIER_DOC \
+ "The *HexModifier* class transforms a byte pattern into its" \
+ " corresponding byte sequence in lower case." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " HexModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_hex_modifier_type(void)
+{
+ static PyMethodDef py_scan_hex_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_hex_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_hex_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.HexModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_HEX_MODIFIER_DOC,
+
+ .tp_methods = py_scan_hex_modifier_methods,
+ .tp_getset = py_scan_hex_modifier_getseters,
+
+ .tp_init = py_scan_hex_modifier_init,
+ .tp_new = py_scan_hex_modifier_new,
+
+ };
+
+ return &py_scan_hex_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....HexModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_hex_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'HexModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_hex_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_HEX_MODIFIER, 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 transmission d'octets à l'identique. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_hex_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_hex_modifier_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 hex modifier");
+ break;
+
+ case 1:
+ *((GScanHexModifier **)dst) = G_SCAN_HEX_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
new file mode 100644
index 0000000..5d70a01
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_hex_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.HexModifier'. */
+bool ensure_python_scan_hex_modifier_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_hex_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
new file mode 100644
index 0000000..7c77d63
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
@@ -0,0 +1,320 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "list.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/list.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_modifier_list, G_TYPE_SCAN_MODIFIER_LIST);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_modifier_list_init(PyObject *, PyObject *, PyObject *);
+
+/* Intègre un nouveau transformateur dans une liste. */
+static PyObject *py_scan_modifier_list_add(PyObject *, PyObject *);
+
+/* Fournit les transformateurs associés à la liste. */
+static PyObject *py_scan_modifier_list_get_modifiers(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_scan_modifier_list_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_MODIFIER_LIST_DOC \
+ "The *ModifierList* class is a special modifier which groups a list of" \
+ " modifiers for byte patterns." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ModifierList()" \
+ "\n" \
+ "The keyword for such a modifier is *(list)*."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = projet d'étude à manipuler. *
+* args = arguments accompagnant l'appel. *
+* *
+* Description : Intègre un nouveau transformateur dans une liste. *
+* *
+* Retour : Bilan de l'ajout : False si un élément similaire est déjà là.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_modifier_list_add(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Absence de retour Python */
+ GScanTokenModifier *modifier; /* Modificateur à intégrer */
+ int ret; /* Bilan de lecture des args. */
+ GScanModifierList *list; /* Version GLib du type */
+ bool status; /* Bilan de l'opération */
+
+#define SCAN_MODIFIER_LIST_ADD_METHOD PYTHON_METHOD_DEF \
+( \
+ add, "$self, modifier, /", \
+ METH_VARARGS, py_scan_modifier_list, \
+ "Add an extra modifier to the list.\n" \
+ "\n" \
+ "This *modifier* parameter has to be a" \
+ " pychrysalide.analysis.scan.patterns.TokenModifier instance." \
+ "\n" \
+ "The function returns *True* if the provided modifier did not already" \
+ " exist in the list, *False* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_token_modifier, &modifier);
+ if (!ret) return NULL;
+
+ list = G_SCAN_MODIFIER_LIST(pygobject_get(self));
+
+ status = g_scan_modifier_list_add(list, modifier);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit les transformateurs associés à la liste. *
+* *
+* Retour : Liste de modificateurs de séquence d'octets. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_modifier_list_get_modifiers(PyObject *self, void *closure)
+{
+ PyObject *result; /* Résultat à retourner */
+ GScanModifierList *list; /* Version GLib du type */
+ size_t count; /* Nombre de transformateurs */
+ size_t i; /* Boucle de parcours */
+ GScanTokenModifier *modifier; /* Modificateur de la liste */
+
+#define SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ modifiers, py_scan_modifier_list, \
+ "List of all modifiers contained in a list.\n" \
+ "\n" \
+ "The returned value is a tuple of pychrysalide.analysis.scan.patterns.TokenModifier" \
+ " instances." \
+)
+
+ list = G_SCAN_MODIFIER_LIST(pygobject_get(self));
+
+ count = g_scan_modifier_list_count(list);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ {
+ modifier = g_scan_modifier_list_get(list, i);
+
+ PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(modifier)));
+
+ g_object_unref(modifier);
+
+ }
+
+ 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_scan_modifier_list_type(void)
+{
+ static PyMethodDef py_scan_modifier_list_methods[] = {
+ SCAN_MODIFIER_LIST_ADD_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_modifier_list_getseters[] = {
+ SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_modifier_list_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.ModifierList",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_MODIFIER_LIST_DOC,
+
+ .tp_methods = py_scan_modifier_list_methods,
+ .tp_getset = py_scan_modifier_list_getseters,
+
+ .tp_init = py_scan_modifier_list_init,
+ .tp_new = py_scan_modifier_list_new,
+
+ };
+
+ return &py_scan_modifier_list_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....ModifierList'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_modifier_list_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ModifierList' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_modifier_list_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_MODIFIER_LIST, 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 liste de transormations d'octets. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_modifier_list(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_modifier_list_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 modifier list");
+ break;
+
+ case 1:
+ *((GScanModifierList **)dst) = G_SCAN_MODIFIER_LIST(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
new file mode 100644
index 0000000..133de8d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_modifier_list_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ModifierList'. */
+bool ensure_python_scan_modifier_list_is_registered(void);
+
+/* Tente de convertir en liste de transormations d'octets. */
+int convert_to_scan_modifier_list(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
new file mode 100644
index 0000000..ae450dc
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
@@ -0,0 +1,112 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire modifiers en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "hex.h"
+#include "list.h"
+#include "plain.h"
+#include "rev.h"
+#include "xor.h"
+#include "../../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis....modifiers' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_modifiers_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_modifiers_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns.modifiers",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_modifiers_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis...patterns.modifiers'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_modifiers_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_scan_hex_modifier_is_registered();
+ if (result) result = ensure_python_scan_modifier_list_is_registered();
+ if (result) result = ensure_python_scan_plain_modifier_is_registered();
+ if (result) result = ensure_python_scan_reverse_modifier_is_registered();
+ if (result) result = ensure_python_scan_xor_modifier_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
new file mode 100644
index 0000000..8094efc
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire modifiers en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns.modifiers' à un module Python. */
+bool add_analysis_scan_patterns_modifiers_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns.modifiers'. */
+bool populate_analysis_scan_patterns_modifiers_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
new file mode 100644
index 0000000..7a260c1
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "plain.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/plain.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_plain_modifier, G_TYPE_SCAN_PLAIN_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_plain_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_plain_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_PLAIN_MODIFIER_DOC \
+ "The *PlainModifier* class provide an transmision of a byte pattern" \
+ " without any modification." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " PlainModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_plain_modifier_type(void)
+{
+ static PyMethodDef py_scan_plain_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_plain_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_plain_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.PlainModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_PLAIN_MODIFIER_DOC,
+
+ .tp_methods = py_scan_plain_modifier_methods,
+ .tp_getset = py_scan_plain_modifier_getseters,
+
+ .tp_init = py_scan_plain_modifier_init,
+ .tp_new = py_scan_plain_modifier_new,
+
+ };
+
+ return &py_scan_plain_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....PlainModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_plain_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'PlainModifier' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_plain_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_PLAIN_MODIFIER, 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 transmission d'octets à l'identique. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_plain_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_plain_modifier_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 plain modifier");
+ break;
+
+ case 1:
+ *((GScanPlainModifier **)dst) = G_SCAN_PLAIN_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
new file mode 100644
index 0000000..03949d8
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_plain_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.PlainModifier'. */
+bool ensure_python_scan_plain_modifier_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_plain_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
new file mode 100644
index 0000000..841e929
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "rev.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/rev.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_reverse_modifier, G_TYPE_SCAN_REVERSE_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_reverse_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_reverse_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_HEX_MODIFIER_DOC \
+ "The *ReverseModifier* class transforms a byte pattern by reversing" \
+ " the order of each bytes." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ReverseModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_reverse_modifier_type(void)
+{
+ static PyMethodDef py_scan_reverse_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_reverse_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_reverse_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_HEX_MODIFIER_DOC,
+
+ .tp_methods = py_scan_reverse_modifier_methods,
+ .tp_getset = py_scan_reverse_modifier_getseters,
+
+ .tp_init = py_scan_reverse_modifier_init,
+ .tp_new = py_scan_reverse_modifier_new,
+
+ };
+
+ return &py_scan_reverse_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....ReverseModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_reverse_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python ReverseModifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_reverse_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REVERSE_MODIFIER, 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 transformation d'octets par inverse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_reverse_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_reverse_modifier_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 reverse modifier");
+ break;
+
+ case 1:
+ *((GScanReverseModifier **)dst) = G_SCAN_REVERSE_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
new file mode 100644
index 0000000..fe10e1e
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/rev.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_reverse_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier'. */
+bool ensure_python_scan_reverse_modifier_is_registered(void);
+
+/* Tente de convertir en transformation d'octets par inverse. */
+int convert_to_scan_reverse_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c
new file mode 100644
index 0000000..17a32f4
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c
@@ -0,0 +1,210 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * xor.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "xor.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/xor.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_xor_modifier, G_TYPE_SCAN_XOR_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_xor_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_xor_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_XOR_MODIFIER_DOC \
+ "The *XorModifier* class transforms a byte pattern by XORing bytes.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " XorModifier()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_xor_modifier_type(void)
+{
+ static PyMethodDef py_scan_xor_modifier_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_xor_modifier_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_xor_modifier_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.XorModifier",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_XOR_MODIFIER_DOC,
+
+ .tp_methods = py_scan_xor_modifier_methods,
+ .tp_getset = py_scan_xor_modifier_getseters,
+
+ .tp_init = py_scan_xor_modifier_init,
+ .tp_new = py_scan_xor_modifier_new,
+
+ };
+
+ return &py_scan_xor_modifier_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....XorModifier'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_xor_modifier_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python XorModifier */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_xor_modifier_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_token_modifier_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_XOR_MODIFIER, 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 transformation d'octets par inverse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_xor_modifier(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_xor_modifier_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 XOR modifier");
+ break;
+
+ case 1:
+ *((GScanXorModifier **)dst) = G_SCAN_XOR_MODIFIER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h
new file mode 100644
index 0000000..7b9bb69
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * xor.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_xor_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.XorModifier'. */
+bool ensure_python_scan_xor_modifier_is_registered(void);
+
+/* Tente de convertir en transformation d'octets par inverse. */
+int convert_to_scan_xor_modifier(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.c b/plugins/pychrysalide/analysis/scan/patterns/module.c
new file mode 100644
index 0000000..123b23a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.c
@@ -0,0 +1,114 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire patterns en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "backend.h"
+#include "modifier.h"
+#include "backends/module.h"
+#include "modifiers/module.h"
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.scan.patterns' à un module Python.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_module);
+
+ result = (module != NULL);
+
+ if (result) result = add_analysis_scan_patterns_backends_module(module);
+ if (result) result = add_analysis_scan_patterns_modifiers_module(module);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis.scan.patterns'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_engine_backend_is_registered();
+ if (result) result = ensure_python_scan_token_modifier_is_registered();
+
+ if (result) result = populate_analysis_scan_patterns_backends_module();
+ if (result) result = populate_analysis_scan_patterns_modifiers_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.h b/plugins/pychrysalide/analysis/scan/patterns/module.h
new file mode 100644
index 0000000..bc25129
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire patterns en tant que module
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns' à un module Python. */
+bool add_analysis_scan_patterns_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns'. */
+bool populate_analysis_scan_patterns_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c
new file mode 100644
index 0000000..bc58c9a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/scanner.c
@@ -0,0 +1,487 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.c - équivalent Python du fichier "analysis/scan/scanner.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "scanner.h"
+
+
+#include <malloc.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/context.h>
+#include <analysis/scan/scanner-int.h>
+
+
+#include "context.h"
+#include "options.h"
+#include "../content.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(content_scanner, G_TYPE_CONTENT_SCANNER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_content_scanner_init(PyObject *, PyObject *, PyObject *);
+
+/* Lance une analyse d'un contenu binaire. */
+static PyObject *py_content_scanner_analyze(PyObject *, PyObject *);
+
+/* Convertit un gestionnaire de recherches en JSON. */
+static PyObject *py_content_scanner_convert_to_json(PyObject *, PyObject *);
+
+/* Indique le chemin d'un éventuel fichier de source. */
+static PyObject *py_content_scanner_get_filename(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_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *text; /* Contenu de règles à traiter */
+ Py_ssize_t len; /* Taille de ce nom */
+ const char *filename; /* Fichier de définitions */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "text", "filename", NULL };
+
+#define CONTENT_SCANNER_DOC \
+ "A ContentScanner object provides support for rules processing" \
+ " against binary contents.\n" \
+ "\n" \
+ "Instances can be created using one of the following" \
+ " constructors:\n" \
+ "\n" \
+ " ContentScanner(text=str)" \
+ "\n" \
+ " ContentScanner(filename=str)" \
+ "\n" \
+ "Where *text* is a string for the rules definitions and" \
+ " *filename* an alternative string for a path pointing to a" \
+ " definition file."
+
+ /* Récupération des paramètres */
+
+ text = NULL;
+ len = 0;
+ filename = NULL;
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "|s#s", kwlist, &text, &len, &filename);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ if (text != NULL)
+ {
+ if (!g_content_scanner_create_from_text(scanner, text, len))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner."));
+ return -1;
+ }
+
+ }
+
+ else if (filename != NULL)
+ {
+ if (!g_content_scanner_create_from_file(scanner, filename))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner."));
+ return -1;
+ }
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create empty content scanner."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Lance une analyse d'un contenu binaire. *
+* *
+* Retour : Contexte de suivi pour l'analyse menée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_analyze(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanOptions *options; /* Paramètres d'analyse */
+ GBinContent *content; /* Contenu binaire à traiter */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ GScanContext *context; /* Contexte de suivi */
+
+#define CONTENT_SCANNER_ANALYZE_METHOD PYTHON_METHOD_DEF \
+( \
+ analyze, "$self, options, content, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Run a scan against a binary content.\n" \
+ "\n" \
+ "The *content* argument is a pychrysalide.analysis.BinContent" \
+ " object pointing to data to analyze.\n" \
+ "\n" \
+ "The method returns a pychrysalide.analysis.scan.ScanContext" \
+ " object tracking all the scan results." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&O&", convert_to_scan_options, &options, convert_to_binary_content, &content);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ context = g_content_scanner_analyze(scanner, options, content);
+
+ result = pygobject_new(G_OBJECT(context));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Convertit un gestionnaire de recherches en texte. *
+* *
+* Retour : Données textuelles ou None en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_convert_to_text(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanContext *context; /* Contexte d'analyse */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ char *out; /* Données en sortie */
+
+#define CONTENT_SCANNER_CONVERT_TO_TEXT_METHOD PYTHON_METHOD_DEF \
+( \
+ convert_to_text, "$self, context, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Output a scan results as text.\n" \
+ "\n" \
+ "The *context* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance provided by a previous call to *self.analyze()*. This" \
+ " context stores all the scan results.\n" \
+ "\n" \
+ "The method returns a string value, or *None* in case of failure." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_context, &context);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ out = g_content_scanner_convert_to_text(scanner, context);
+
+ if (out != NULL)
+ {
+ result = PyUnicode_FromString(out);
+ free(out);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Convertit un gestionnaire de recherches en JSON. *
+* *
+* Retour : Données textuelles au format JSON ou None en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_convert_to_json(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanContext *context; /* Contexte d'analyse */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ char *out; /* Données en sortie */
+
+#define CONTENT_SCANNER_CONVERT_TO_JSON_METHOD PYTHON_METHOD_DEF \
+( \
+ convert_to_json, "$self, context, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Output a scan results as JSON data.\n" \
+ "\n" \
+ "The *context* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance provided by a previous call to *self.analyze()*. This" \
+ " context stores all the scan results.\n" \
+ "\n" \
+ "The method returns JSON data as a string value, or *None* in case" \
+ " of failure." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_context, &context);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ out = g_content_scanner_convert_to_json(scanner, context);
+
+ if (out != NULL)
+ {
+ result = PyUnicode_FromString(out);
+ free(out);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le chemin d'un éventuel fichier de source. *
+* *
+* Retour : Chemin d'un éventuel fichier de définitions ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_get_filename(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GContentScanner *scanner; /* Analyseur à consulter */
+ const char *filename; /* Chemin d'accès à transmettre*/
+
+#define CONTENT_SCANNER_FILENAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ filename, py_content_scanner, \
+ "Provide the access path to the source file of the rules'" \
+ " definition, or *None* if these rules have not been loaded"\
+ " from memory." \
+)
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ filename = g_content_scanner_get_filename(scanner);
+
+ if (filename != NULL)
+ result = PyUnicode_FromString(filename);
+
+ 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_content_scanner_type(void)
+{
+ static PyMethodDef py_content_scanner_methods[] = {
+ CONTENT_SCANNER_ANALYZE_METHOD,
+ CONTENT_SCANNER_CONVERT_TO_TEXT_METHOD,
+ CONTENT_SCANNER_CONVERT_TO_JSON_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_content_scanner_getseters[] = {
+ CONTENT_SCANNER_FILENAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_content_scanner_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ContentScanner",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = CONTENT_SCANNER_DOC,
+
+ .tp_methods = py_content_scanner_methods,
+ .tp_getset = py_content_scanner_getseters,
+
+ .tp_init = py_content_scanner_init,
+ .tp_new = py_content_scanner_new,
+
+ };
+
+ return &py_content_scanner_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ContentScanner. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_content_scanner_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ContentScanner'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_content_scanner_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_SCANNER, 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 scanner de contenus binaires. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_content_scanner(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_content_scanner_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 content scanner");
+ break;
+
+ case 1:
+ *((GContentScanner **)dst) = G_CONTENT_SCANNER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/scanner.h b/plugins/pychrysalide/analysis/scan/scanner.h
new file mode 100644
index 0000000..b3b1baf
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/scanner.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.h - prototypes pour l'équivalent Python du fichier "analysis/scan/scanner.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_content_scanner_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ContentScanner'. */
+bool ensure_python_content_scanner_is_registered(void);
+
+/* Tente de convertir en scanner de contenus binaires. */
+int convert_to_content_scanner(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H */
diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c
new file mode 100644
index 0000000..6ea87b8
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/space.c
@@ -0,0 +1,283 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - équivalent Python du fichier "analysis/scan/space.c"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "space.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/item.h>
+#include <analysis/scan/space-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+
+
+#include "item.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_namespace, G_TYPE_SCAN_NAMESPACE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_namespace_init(PyObject *, PyObject *, PyObject *);
+
+/* Intègre un nouvel élément dans l'esapce de noms. */
+static PyObject *py_scan_namespace_register_item(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_namespace_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *name; /* Désignation de l'espace */
+ int ret; /* Bilan de lecture des args. */
+ GScanNamespace *space; /* Création GLib à transmettre */
+
+#define SCAN_NAMESPACE_DOC \
+ "ScanNamespace defines a group of properties and functions for a" \
+ " given scan theme.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanNamespace(name)" \
+ "\n" \
+ "Where *name* is a string providing the name of the new namespace."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "s", &name);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Elément de base */
+
+ space = G_SCAN_NAMESPACE(pygobject_get(self));
+
+ if (!g_scan_namespace_create(space, name))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create scan namespace."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet représentant une table de chaînes. *
+* args = arguments fournis pour l'opération. *
+* *
+* Description : Intègre un nouvel élément dans l'esapce de noms. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_namespace_register_item(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GScanRegisteredItem *item; /* Elément d'évaluation à lier */
+ int ret; /* Bilan de lecture des args. */
+ GScanNamespace *space; /* Version native */
+ bool status; /* Bilan de l'opération */
+
+#define SCAN_NAMESPACE_REGISTER_ITEM_METHOD PYTHON_METHOD_DEF \
+( \
+ register_item, "$self, item, /", \
+ METH_VARARGS, py_scan_namespace, \
+ "Include an item into a namespace.\n" \
+ "\n" \
+ "The *item* argument has to be a pychrysalide.analysis.scan.RegisteredItem" \
+ " instance.\n" \
+ "\n" \
+ "The function returns a boolean value translating the operation status:" \
+ " *True* in case of success, *False* for a failure.\n" \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_scan_registered_item, &item);
+ if (!ret) return NULL;
+
+ space = G_SCAN_NAMESPACE(pygobject_get(self));
+
+ status = g_scan_namespace_register_item(space, item);
+
+ result = status ? Py_True : Py_False;
+ 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_scan_namespace_type(void)
+{
+ static PyMethodDef py_scan_namespace_methods[] = {
+ SCAN_NAMESPACE_REGISTER_ITEM_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_namespace_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_namespace_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanNamespace",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_NAMESPACE_DOC,
+
+ .tp_methods = py_scan_namespace_methods,
+ .tp_getset = py_scan_namespace_getseters,
+
+ .tp_init = py_scan_namespace_init,
+ .tp_new = py_scan_namespace_new,
+
+ };
+
+ return &py_scan_namespace_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanNamespace'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_namespace_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanNamespace' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_namespace_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_NAMESPACE, 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 espace de noms pour scan. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_namespace(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_namespace_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 scan namespace");
+ break;
+
+ case 1:
+ *((GScanNamespace **)dst) = G_SCAN_NAMESPACE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/space.h b/plugins/pychrysalide/analysis/scan/space.h
new file mode 100644
index 0000000..0166c04
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/space.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour l'équivalent Python du fichier "analysis/scan/space.h"
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_namespace_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanNamespace'. */
+bool ensure_python_scan_namespace_is_registered(void);
+
+/* Tente de convertir en espace de noms pour scan. */
+int convert_to_scan_namespace(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H */
diff --git a/plugins/pychrysalide/analysis/storage/Makefile.am b/plugins/pychrysalide/analysis/storage/Makefile.am
index 01240cb..d0a4df4 100644
--- a/plugins/pychrysalide/analysis/storage/Makefile.am
+++ b/plugins/pychrysalide/analysis/storage/Makefile.am
@@ -9,19 +9,10 @@ libpychrysaanalysisstorage_la_SOURCES = \
storage.h storage.c \
tpmem.h tpmem.c
-libpychrysaanalysisstorage_la_LIBADD =
-
-libpychrysaanalysisstorage_la_LDFLAGS =
+libpychrysaanalysisstorage_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysisstorage_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/analysis/storage/cache.c b/plugins/pychrysalide/analysis/storage/cache.c
index 9859623..8cd5bac 100644
--- a/plugins/pychrysalide/analysis/storage/cache.c
+++ b/plugins/pychrysalide/analysis/storage/cache.c
@@ -100,7 +100,7 @@ static PyObject *py_object_cache_new(PyTypeObject *type, PyObject *args, PyObjec
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -304,7 +304,7 @@ bool ensure_python_object_cache_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_CACHE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_CACHE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/storage/storage.c b/plugins/pychrysalide/analysis/storage/storage.c
index 107980e..c54fe0f 100644
--- a/plugins/pychrysalide/analysis/storage/storage.c
+++ b/plugins/pychrysalide/analysis/storage/storage.c
@@ -33,7 +33,6 @@
#include "serialize.h"
-#include "../loaded.h"
#include "../../access.h"
#include "../../helpers.h"
#include "../../common/packed.h"
@@ -54,8 +53,11 @@ static int py_object_storage_init(PyObject *, PyObject *, PyObject *);
/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-/* Ajoute le support d'un nouveau groupe d'objets construits. */
-static PyObject *py_object_storage_add_backend(PyObject *, PyObject *);
+/* Charge le support d'une conservation d'objets en place. */
+static PyObject *py_object_storage_load(PyObject *, PyObject *);
+
+/* Sauvegarde le support d'une conservation d'objets en place. */
+static PyObject *py_object_storage_store(PyObject *, PyObject *);
/* Charge un objet à partir de données rassemblées. */
static PyObject *py_object_storage_load_object(PyObject *, PyObject *);
@@ -113,7 +115,7 @@ static PyObject *py_object_storage_new(PyTypeObject *type, PyObject *args, PyObj
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -152,7 +154,7 @@ static PyObject *py_object_storage_new(PyTypeObject *type, PyObject *args, PyObj
static int py_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- GLoadedContent *loaded; /* Contenu chargé et traité */
+ const char *hash; /* Empreinte de contenu */
int ret; /* Bilan de lecture des args. */
GObjectStorage *storage; /* Mécanismes natifs */
@@ -162,14 +164,14 @@ static int py_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " ObjectStorage(loaded)" \
+ " ObjectStorage(hash)" \
"\n" \
- "Where *loaded* is a pychrysalide.analysis.LoadedContent instance" \
- " linked to the objects which can apply for a storage process."
+ "Where *hash* should a string built from the checksum of the" \
+ " relative binary content linked to the storage.pychrysalide."
/* Récupération des paramètres */
- ret = PyArg_ParseTuple(args, "O&", convert_to_loaded_content, &loaded);
+ ret = PyArg_ParseTuple(args, "s", &hash);
if (!ret) return -1;
/* Initialisation d'un objet GLib */
@@ -181,8 +183,7 @@ static int py_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds
storage = G_OBJECT_STORAGE(pygobject_get(self));
- storage->loaded = loaded;
- g_object_ref(G_OBJECT(loaded));
+ storage->hash = strdup(hash);
return 0;
@@ -200,7 +201,61 @@ static int py_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds
* Paramètres : self = classe représentant une mémorisation de types. *
* args = arguments fournis à l'appel. *
* *
-* Description : Ajoute le support d'un nouveau groupe d'objets construits. *
+* Description : Charge le support d'une conservation d'objets en place. *
+* *
+* Retour : Gestionnaire de conservations construit ou None si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_object_storage_load(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Emplacement à retourner */
+ packed_buffer_t *pbuf; /* Tampon de données à employer*/
+ int ret; /* Bilan de lecture des args. */
+ GObjectStorage *storage; /* Mécanismes natifs */
+
+#define OBJECT_STORAGE_LOAD_METHOD PYTHON_METHOD_DEF \
+( \
+ load, "pbuf, /", \
+ METH_STATIC | METH_VARARGS, py_object_storage, \
+ "Construct a new storage from a buffer.\n" \
+ "\n" \
+ "The *pbuf* has to be an instance of type" \
+ " pychrysalide.common.PackedBuffer.\n" \
+ "\n" \
+ "The result is a new pychrysalide.analysis.storage.ObjectStorage" \
+ " object on success, *None* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf);
+ if (!ret) return NULL;
+
+ storage = g_object_storage_load(pbuf);
+
+ if (storage == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ {
+ result = pygobject_new(G_OBJECT(storage));
+ g_object_unref(G_OBJECT(storage));
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant une mémorisation de types. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Sauvegarde le support d'une conservation d'objets en place. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -208,37 +263,32 @@ static int py_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds
* *
******************************************************************************/
-static PyObject *py_object_storage_add_backend(PyObject *self, PyObject *args)
+static PyObject *py_object_storage_store(PyObject *self, PyObject *args)
{
- PyObject *result; /* Bilan à retourner */
- const char *name; /* Désignation de groupe */
- const char *filename; /* Nom de fichier à associer */
+ PyObject *result; /* Emplacement à retourner */
+ packed_buffer_t *pbuf; /* Tampon de données à employer*/
int ret; /* Bilan de lecture des args. */
GObjectStorage *storage; /* Mécanismes natifs */
bool status; /* Bilan de l'opération */
-#define OBJECT_STORAGE_ADD_BACKEND_METHOD PYTHON_METHOD_DEF \
-( \
- add_backend, "$self, name, /, filename", \
- METH_VARARGS, py_object_storage, \
- "Add storage support for a new kind of GLib objects.\n" \
- "\n" \
- "The *name* is a string label for the group of target objects" \
- " and the optional *filename* points to a file used to load" \
- " objects.\n" \
- "\n" \
- "The result is a boolean value indicating the status of" \
- " the operation: True for success, False for failure." \
+#define OBJECT_STORAGE_STORE_METHOD PYTHON_METHOD_DEF \
+( \
+ store, "$self, pbuf, /", \
+ METH_VARARGS, py_object_storage, \
+ "Save a storage into a buffer.\n" \
+ "\n" \
+ "The *pbuf* has to be an instance of type" \
+ " pychrysalide.common.PackedBuffer.\n" \
+ "\n" \
+ "The result is *True* on success, *False* otherwise." \
)
- filename = NULL;
-
- ret = PyArg_ParseTuple(args, "s|s", &name, &filename);
+ ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf);
if (!ret) return NULL;
storage = G_OBJECT_STORAGE(pygobject_get(self));
- status = g_object_storage_add_backend(storage, name, filename);
+ status = g_object_storage_store(storage, pbuf);
result = status ? Py_True : Py_False;
Py_INCREF(result);
@@ -488,7 +538,8 @@ static PyObject *py_object_storage_pack_object(PyObject *self, PyObject *args)
PyTypeObject *get_python_object_storage_type(void)
{
static PyMethodDef py_object_storage_methods[] = {
- OBJECT_STORAGE_ADD_BACKEND_METHOD,
+ OBJECT_STORAGE_LOAD_METHOD,
+ OBJECT_STORAGE_STORE_METHOD,
OBJECT_STORAGE_LOAD_OBJECT_METHOD,
OBJECT_STORAGE_UNPACK_OBJECT_METHOD,
OBJECT_STORAGE_STORE_OBJECT_METHOD,
@@ -550,7 +601,7 @@ bool ensure_python_object_storage_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/storage/tpmem.c b/plugins/pychrysalide/analysis/storage/tpmem.c
index 8df20b2..ae07008 100644
--- a/plugins/pychrysalide/analysis/storage/tpmem.c
+++ b/plugins/pychrysalide/analysis/storage/tpmem.c
@@ -52,8 +52,8 @@ static int py_type_memory_init(PyObject *, PyObject *, PyObject *);
/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
-/* Apprend tous les types mémorisés dans un flux. */
-static PyObject *py_type_memory_read_types(PyObject *, PyObject *);
+/* Apprend tous les types mémorisés dans un tampon. */
+static PyObject *py_type_memory_load_types(PyObject *, PyObject *);
/* Crée une nouvelle instance d'objet à partir de son type. */
static PyObject *py_type_memory_create_object(PyObject *, PyObject *);
@@ -61,8 +61,8 @@ static PyObject *py_type_memory_create_object(PyObject *, PyObject *);
/* Sauvegarde le type d'un objet instancié. */
static PyObject *py_type_memory_store_object_gtype(PyObject *, PyObject *);
-/* Enregistre tous les types mémorisés dans un flux. */
-static PyObject *py_type_memory_write_types(PyObject *, PyObject *);
+/* Enregistre tous les types mémorisés dans un tampon. */
+static PyObject *py_type_memory_store_types(PyObject *, PyObject *);
@@ -108,7 +108,7 @@ static PyObject *py_type_memory_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -178,7 +178,7 @@ static int py_type_memory_init(PyObject *self, PyObject *args, PyObject *kwds)
* Paramètres : self = classe représentant une mémorisation de types. *
* args = arguments fournis à l'appel. *
* *
-* Description : Apprend tous les types mémorisés dans un flux. *
+* Description : Apprend tous les types mémorisés dans un tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -186,36 +186,36 @@ static int py_type_memory_init(PyObject *self, PyObject *args, PyObject *kwds)
* *
******************************************************************************/
-static PyObject *py_type_memory_read_types(PyObject *self, PyObject *args)
+static PyObject *py_type_memory_load_types(PyObject *self, PyObject *args)
{
PyObject *result; /* Bilan à retourner */
- int fd; /* Flux ouvert en lecture */
+ packed_buffer_t *pbuf; /* Tampon à consulter */
int ret; /* Bilan de lecture des args. */
GTypeMemory *tpmem; /* Mémorisation native */
bool status; /* Bilan de l'opération */
-#define TYPE_MEMORY_READ_TYPES_METHOD PYTHON_METHOD_DEF \
+#define TYPE_MEMORY_LOAD_TYPES_METHOD PYTHON_METHOD_DEF \
( \
- read_types, "$self, fd", \
+ load_types, "$self, pbuf", \
METH_VARARGS, py_type_memory, \
- "Read types from a stream.\n" \
+ "Read types from a buffer.\n" \
"\n" \
"This operation is usually handled internally by the" \
" Chrysalide's core.\n" \
"\n" \
- "The *fd* parameter is an integer representing a valid" \
- " identifier for a file descriptor opened for reading." \
+ "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\
+ " instance providing buffered data to read." \
"\n" \
"The result is a boolean value indicating the status of" \
" the operation: True for success, False for failure." \
)
- ret = PyArg_ParseTuple(args, "i", &fd);
+ ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf);
if (!ret) return NULL;
tpmem = G_TYPE_MEMORY(pygobject_get(self));
- status = g_type_memory_read_types(tpmem, fd);
+ status = g_type_memory_load_types(tpmem, pbuf);
result = status ? Py_True : Py_False;
Py_INCREF(result);
@@ -330,7 +330,7 @@ static PyObject *py_type_memory_store_object_gtype(PyObject *self, PyObject *arg
* Paramètres : self = classe représentant une mémorisation de types. *
* args = arguments fournis à l'appel. *
* *
-* Description : Enregistre tous les types mémorisés dans un flux. *
+* Description : Enregistre tous les types mémorisés dans un tampon. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -338,36 +338,36 @@ static PyObject *py_type_memory_store_object_gtype(PyObject *self, PyObject *arg
* *
******************************************************************************/
-static PyObject *py_type_memory_write_types(PyObject *self, PyObject *args)
+static PyObject *py_type_memory_store_types(PyObject *self, PyObject *args)
{
PyObject *result; /* Bilan à retourner */
- int fd; /* Flux ouvert en lecture */
+ packed_buffer_t *pbuf; /* Tampon à consulter */
int ret; /* Bilan de lecture des args. */
GTypeMemory *tpmem; /* Mémorisation native */
bool status; /* Bilan de l'opération */
-#define TYPE_MEMORY_WRITE_TYPES_METHOD PYTHON_METHOD_DEF \
+#define TYPE_MEMORY_STORE_TYPES_METHOD PYTHON_METHOD_DEF \
( \
- write_types, "$self, fd", \
+ store_types, "$self, pbuf", \
METH_VARARGS, py_type_memory, \
- "Write types into a stream.\n" \
+ "Write types into a buffer.\n" \
"\n" \
"This operation is usually handled internally by the" \
" Chrysalide's core.\n" \
"\n" \
- "The *fd* parameter is an integer representing a valid" \
- " identifier for a file descriptor opened for writing." \
+ "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\
+ " instance providing buffered data to read." \
"\n" \
"The result is a boolean value indicating the status of" \
" the operation: True for success, False for failure." \
)
- ret = PyArg_ParseTuple(args, "i", &fd);
+ ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf);
if (!ret) return NULL;
tpmem = G_TYPE_MEMORY(pygobject_get(self));
- status = g_type_memory_write_types(tpmem, fd);
+ status = g_type_memory_store_types(tpmem, pbuf);
result = status ? Py_True : Py_False;
Py_INCREF(result);
@@ -392,10 +392,10 @@ static PyObject *py_type_memory_write_types(PyObject *self, PyObject *args)
PyTypeObject *get_python_type_memory_type(void)
{
static PyMethodDef py_type_memory_methods[] = {
- TYPE_MEMORY_READ_TYPES_METHOD,
+ TYPE_MEMORY_LOAD_TYPES_METHOD,
TYPE_MEMORY_CREATE_OBJECT_METHOD,
TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD,
- TYPE_MEMORY_WRITE_TYPES_METHOD,
+ TYPE_MEMORY_STORE_TYPES_METHOD,
{ NULL }
};
@@ -453,7 +453,7 @@ bool ensure_python_type_memory_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/type.c b/plugins/pychrysalide/analysis/type.c
index 86a0ffb..ea8affd 100644
--- a/plugins/pychrysalide/analysis/type.c
+++ b/plugins/pychrysalide/analysis/type.c
@@ -158,7 +158,7 @@ static PyObject *py_data_type_new(PyTypeObject *type, PyObject *args, PyObject *
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -220,6 +220,7 @@ static void py_data_type_init_gclass(GDataTypeClass *class, gpointer unused)
static guint py_data_type_hash_wrapper(const GDataType *type)
{
guint result; /* Empreinte à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
@@ -234,6 +235,8 @@ static guint py_data_type_hash_wrapper(const GDataType *type)
result = 0;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(type));
if (has_python_method(pyobj, "_hash"))
@@ -252,6 +255,8 @@ static guint py_data_type_hash_wrapper(const GDataType *type)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -272,6 +277,7 @@ static guint py_data_type_hash_wrapper(const GDataType *type)
static GDataType *py_data_type_dup_wrapper(const GDataType *type)
{
GDataType *result; /* Copie à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
@@ -287,6 +293,8 @@ static GDataType *py_data_type_dup_wrapper(const GDataType *type)
result = NULL;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(type));
if (has_python_method(pyobj, "_dup"))
@@ -308,6 +316,8 @@ static GDataType *py_data_type_dup_wrapper(const GDataType *type)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -329,6 +339,7 @@ static GDataType *py_data_type_dup_wrapper(const GDataType *type)
static char *py_data_type_to_string_wrapper(const GDataType *type, bool include)
{
char *result; /* Etiquette à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *arg; /* Version Python de l'argument*/
PyObject *args; /* Arguments pour l'appel */
@@ -349,6 +360,8 @@ static char *py_data_type_to_string_wrapper(const GDataType *type, bool include)
result = NULL;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(type));
if (has_python_method(pyobj, "_to_string"))
@@ -375,6 +388,8 @@ static char *py_data_type_to_string_wrapper(const GDataType *type, bool include)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -395,6 +410,7 @@ static char *py_data_type_to_string_wrapper(const GDataType *type, bool include)
static bool py_data_type_handle_namespaces_wrapper(const GDataType *type)
{
bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
@@ -411,6 +427,8 @@ static bool py_data_type_handle_namespaces_wrapper(const GDataType *type)
result = true;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(type));
if (has_python_method(pyobj, "_handle_namespaces"))
@@ -425,6 +443,8 @@ static bool py_data_type_handle_namespaces_wrapper(const GDataType *type)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -445,6 +465,7 @@ static bool py_data_type_handle_namespaces_wrapper(const GDataType *type)
static bool py_data_type_is_pointer_wrapper(const GDataType *type)
{
bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
@@ -461,6 +482,8 @@ static bool py_data_type_is_pointer_wrapper(const GDataType *type)
result = false;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(type));
if (has_python_method(pyobj, "_is_pointer"))
@@ -475,6 +498,8 @@ static bool py_data_type_is_pointer_wrapper(const GDataType *type)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -495,6 +520,7 @@ static bool py_data_type_is_pointer_wrapper(const GDataType *type)
static bool py_data_type_is_reference_wrapper(const GDataType *type)
{
bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
@@ -511,6 +537,8 @@ static bool py_data_type_is_reference_wrapper(const GDataType *type)
result = false;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(type));
if (has_python_method(pyobj, "_is_reference"))
@@ -525,6 +553,8 @@ static bool py_data_type_is_reference_wrapper(const GDataType *type)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -1095,7 +1125,7 @@ bool ensure_python_data_type_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_DATA_TYPE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_DATA_TYPE, type))
return false;
if (!define_analysis_data_type_constants(type))
diff --git a/plugins/pychrysalide/analysis/types/Makefile.am b/plugins/pychrysalide/analysis/types/Makefile.am
index 8f1799f..697c998 100644
--- a/plugins/pychrysalide/analysis/types/Makefile.am
+++ b/plugins/pychrysalide/analysis/types/Makefile.am
@@ -1,30 +1,23 @@
noinst_LTLIBRARIES = libpychrysaanalysistypes.la
-libpychrysaanalysistypes_la_SOURCES = \
- array.h array.c \
- basic.h basic.c \
- constants.h constants.c \
- cse.h cse.c \
- encaps.h encaps.c \
- expr.h expr.c \
- literal.h literal.c \
- module.h module.c \
- override.h override.c \
- proto.h proto.c \
+libpychrysaanalysistypes_la_SOURCES = \
+ array.h array.c \
+ basic.h basic.c \
+ constants.h constants.c \
+ cse.h cse.c \
+ encaps.h encaps.c \
+ expr.h expr.c \
+ literal.h literal.c \
+ module.h module.c \
+ override.h override.c \
+ proto.h proto.c \
template.h template.c
-libpychrysaanalysistypes_la_LDFLAGS =
+libpychrysaanalysistypes_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysistypes_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/analysis/types/array.c b/plugins/pychrysalide/analysis/types/array.c
index 8055316..88b773e 100644
--- a/plugins/pychrysalide/analysis/types/array.c
+++ b/plugins/pychrysalide/analysis/types/array.c
@@ -423,7 +423,7 @@ bool ensure_python_array_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_ARRAY_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_ARRAY_TYPE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/types/basic.c b/plugins/pychrysalide/analysis/types/basic.c
index 9ae4f8f..19fb9d1 100644
--- a/plugins/pychrysalide/analysis/types/basic.c
+++ b/plugins/pychrysalide/analysis/types/basic.c
@@ -210,7 +210,7 @@ bool ensure_python_basic_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_BASIC_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_BASIC_TYPE, type))
return false;
if (!define_basic_type_constants(type))
diff --git a/plugins/pychrysalide/analysis/types/cse.c b/plugins/pychrysalide/analysis/types/cse.c
index 7701d48..0aab4d9 100644
--- a/plugins/pychrysalide/analysis/types/cse.c
+++ b/plugins/pychrysalide/analysis/types/cse.c
@@ -262,7 +262,7 @@ bool ensure_python_class_enum_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_CLASS_ENUM_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_CLASS_ENUM_TYPE, type))
return false;
if (!define_class_enum_type_constants(type))
diff --git a/plugins/pychrysalide/analysis/types/encaps.c b/plugins/pychrysalide/analysis/types/encaps.c
index 3a5acb5..bc9f4db 100644
--- a/plugins/pychrysalide/analysis/types/encaps.c
+++ b/plugins/pychrysalide/analysis/types/encaps.c
@@ -223,7 +223,7 @@ bool ensure_python_encapsulated_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_ENCAPSULATED_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_ENCAPSULATED_TYPE, type))
return false;
if (!define_encapsulated_type_constants(type))
diff --git a/plugins/pychrysalide/analysis/types/expr.c b/plugins/pychrysalide/analysis/types/expr.c
index 02cb02f..e3b2b0a 100644
--- a/plugins/pychrysalide/analysis/types/expr.c
+++ b/plugins/pychrysalide/analysis/types/expr.c
@@ -201,7 +201,7 @@ bool ensure_python_expr_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_EXPR_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_EXPR_TYPE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/types/literal.c b/plugins/pychrysalide/analysis/types/literal.c
index e00104f..3d9d5e3 100644
--- a/plugins/pychrysalide/analysis/types/literal.c
+++ b/plugins/pychrysalide/analysis/types/literal.c
@@ -136,7 +136,7 @@ bool ensure_python_literal_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_LITERAL_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_LITERAL_TYPE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/types/override.c b/plugins/pychrysalide/analysis/types/override.c
index 896163f..236a34c 100644
--- a/plugins/pychrysalide/analysis/types/override.c
+++ b/plugins/pychrysalide/analysis/types/override.c
@@ -247,7 +247,7 @@ bool ensure_python_override_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_OVERRIDE_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_OVERRIDE_TYPE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/types/proto.c b/plugins/pychrysalide/analysis/types/proto.c
index 7c3ebed..1da3119 100644
--- a/plugins/pychrysalide/analysis/types/proto.c
+++ b/plugins/pychrysalide/analysis/types/proto.c
@@ -349,7 +349,7 @@ bool ensure_python_proto_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_PROTO_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_PROTO_TYPE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/types/template.c b/plugins/pychrysalide/analysis/types/template.c
index 6fc50e4..68f390a 100644
--- a/plugins/pychrysalide/analysis/types/template.c
+++ b/plugins/pychrysalide/analysis/types/template.c
@@ -345,7 +345,7 @@ bool ensure_python_template_type_is_registered(void)
if (!ensure_python_data_type_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_TEMPLATE_TYPE, type, get_python_data_type_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_TEMPLATE_TYPE, type))
return false;
}
diff --git a/plugins/pychrysalide/analysis/variable.c b/plugins/pychrysalide/analysis/variable.c
index 3aeddf4..5f8d490 100644
--- a/plugins/pychrysalide/analysis/variable.c
+++ b/plugins/pychrysalide/analysis/variable.c
@@ -266,7 +266,7 @@ bool ensure_python_binary_variable_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BIN_VARIABLE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BIN_VARIABLE, type))
return false;
}
diff --git a/plugins/pychrysalide/arch/Makefile.am b/plugins/pychrysalide/arch/Makefile.am
index ab4ca23..c113f6e 100644
--- a/plugins/pychrysalide/arch/Makefile.am
+++ b/plugins/pychrysalide/arch/Makefile.am
@@ -1,22 +1,23 @@
noinst_LTLIBRARIES = libpychrysaarch.la
-libpychrysaarch_la_SOURCES = \
- constants.h constants.c \
- context.h context.c \
- instriter.h instriter.c \
- instruction.h instruction.c \
- module.h module.c \
- operand.h operand.c \
- processor.h processor.c \
- register.h register.c \
+libpychrysaarch_la_SOURCES = \
+ constants.h constants.c \
+ context.h context.c \
+ instriter.h instriter.c \
+ instruction.h instruction.c \
+ module.h module.c \
+ operand.h operand.c \
+ processor.h processor.c \
+ register.h register.c \
vmpa.h vmpa.c
-libpychrysaarch_la_LIBADD = \
+libpychrysaarch_la_LIBADD = \
instructions/libpychrysaarchinstructions.la \
operands/libpychrysaarchoperands.la
-libpychrysaarch_la_LDFLAGS =
+libpychrysaarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -24,9 +25,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaarch_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = instructions operands
diff --git a/plugins/pychrysalide/arch/context.c b/plugins/pychrysalide/arch/context.c
index ce1ef01..79c782f 100644
--- a/plugins/pychrysalide/arch/context.c
+++ b/plugins/pychrysalide/arch/context.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * context.c - équivalent Python du fichier "arch/context.h"
+ * context.c - équivalent Python du fichier "arch/context.c"
*
* Copyright (C) 2018 Cyrille Bagard
*
@@ -39,6 +39,7 @@
#include "../helpers.h"
#include "../analysis/db/item.h"
#include "../arch/vmpa.h"
+#include "../format/preload.h"
@@ -120,7 +121,7 @@ static PyObject *py_proc_context_new(PyTypeObject *type, PyObject *args, PyObjec
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -518,7 +519,10 @@ bool ensure_python_proc_context_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PROC_CONTEXT, type, &PyGObject_Type))
+ if (!ensure_python_preload_info_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PROC_CONTEXT, type))
return false;
if (!define_proc_context_constants(type))
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 3606cfe..0a9ba16 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -45,52 +45,7 @@
-/* -------------------- INTERFACE INTERNE POUR EXTENSIONS PYTHON -------------------- */
-
-
-/* Définition générique d'une instruction d'architecture (instance) */
-typedef struct _GPyArchInstruction
-{
- GArchInstruction parent; /* A laisser en premier */
-
- char *cached_keyword; /* Conservation de constante */
-
-} GPyArchInstruction;
-
-
-/* Définition générique d'une instruction d'architecture (classe) */
-typedef struct _GPyArchInstructionClass
-{
- GArchInstructionClass parent; /* A laisser en premier */
-
-} GPyArchInstructionClass;
-
-
-#define G_TYPE_PYARCH_INSTRUCTION g_pyarch_instruction_get_type()
-#define G_PYARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PYARCH_INSTRUCTION, GPyArchInstruction))
-#define G_IS_PYTHON_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PYARCH_INSTRUCTION))
-#define G_PYARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PYARCH_INSTRUCTION, GPyArchInstructionClass))
-#define G_IS_PYTHON_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PYARCH_INSTRUCTION))
-#define G_PYARCH_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PYARCH_INSTRUCTION, GPyArchInstructionClass))
-
-
-/* Indique le type défini pour une instruction d'architecture en Python. */
-GType g_pyarch_instruction_get_type(void);
-
-/* Initialise la classe générique des instructions en Python. */
-static void g_pyarch_instruction_class_init(GPyArchInstructionClass *);
-
-/* Initialise une instance d'opérande d'architecture. */
-static void g_pyarch_instruction_init(GPyArchInstruction *);
-
-/* Supprime toutes les références externes. */
-static void g_pyarch_instruction_dispose(GPyArchInstruction *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_pyarch_instruction_finalize(GPyArchInstruction *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static const char *g_pyarch_instruction_get_keyword(GPyArchInstruction *);
+static G_DEFINE_QUARK(cached_keyword, get_cached_keyword);
@@ -101,11 +56,16 @@ static const char *g_pyarch_instruction_get_keyword(GPyArchInstruction *);
static PyObject *py_arch_instruction_new(PyTypeObject *, PyObject *, PyObject *);
/* Initialise la classe générique des instructions. */
-static void py_arch_instruction_init_gclass(GPyArchInstructionClass *, gpointer);
+static void py_arch_instruction_init_gclass(GArchInstructionClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(arch_instruction, G_TYPE_ARCH_INSTRUCTION, py_arch_instruction_init_gclass);
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_arch_instruction_init(PyObject *, PyObject *, PyObject *);
+/* Fournit le nom humain de l'instruction manipulée. */
+static const char *py_arch_instruction_get_class_keyword(GArchInstruction *);
+
/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
@@ -160,19 +120,16 @@ static PyObject *py_arch_instruction_get_keyword(PyObject *, void *);
/* ---------------------------------------------------------------------------------- */
-/* INTERFACE INTERNE POUR EXTENSIONS PYTHON */
+/* GLUE POUR CREATION DEPUIS PYTHON */
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour une instruction d'architecture en Python. */
-G_DEFINE_TYPE(GPyArchInstruction, g_pyarch_instruction, G_TYPE_ARCH_INSTRUCTION);
-
-
/******************************************************************************
* *
-* Paramètres : klass = classe à initialiser. *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
* *
-* Description : Initialise la classe générique des instructions en Python. *
+* Description : Initialise la classe générique des instructions. *
* *
* Retour : - *
* *
@@ -180,78 +137,62 @@ G_DEFINE_TYPE(GPyArchInstruction, g_pyarch_instruction, G_TYPE_ARCH_INSTRUCTION)
* *
******************************************************************************/
-static void g_pyarch_instruction_class_init(GPyArchInstructionClass *klass)
+static void py_arch_instruction_init_gclass(GArchInstructionClass *class, gpointer unused)
{
- GObjectClass *object; /* Autre version de la classe */
GArchInstructionClass *instr; /* Encore une autre vision... */
- object = G_OBJECT_CLASS(klass);
+ instr = G_ARCH_INSTRUCTION_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_pyarch_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_pyarch_instruction_finalize;
-
- instr = G_ARCH_INSTRUCTION_CLASS(klass);
-
- instr->get_keyword = (get_instruction_keyword_fc)g_pyarch_instruction_get_keyword;
+ instr->get_keyword = (get_instruction_keyword_fc)py_arch_instruction_get_class_keyword;
}
/******************************************************************************
* *
-* Paramètres : instr = instance à initialiser. *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
* *
-* Description : Initialise une instance d'instruction d'architecture. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : - *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_pyarch_instruction_init(GPyArchInstruction *instr)
+static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kwds)
{
+ unsigned short int uid; /* Indentifiant unique de type */
+ const char *keyword; /* Désignation d'instruction */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction à manipuler */
+ GQuark cache_key; /* Emplacement local */
-}
+ static char *kwlist[] = { "uid", "keyword", NULL };
+ /* Récupération des paramètres */
-/******************************************************************************
-* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "Hs", kwlist, &uid, &keyword);
+ if (!ret) return -1;
-static void g_pyarch_instruction_dispose(GPyArchInstruction *instr)
-{
- G_OBJECT_CLASS(g_pyarch_instruction_parent_class)->dispose(G_OBJECT(instr));
+ /* Initialisation d'un objet GLib */
-}
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+ /* Eléments de base */
-/******************************************************************************
-* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
-static void g_pyarch_instruction_finalize(GPyArchInstruction *instr)
-{
- if (instr->cached_keyword)
- free(instr->cached_keyword);
+ cache_key = get_cached_keyword_quark();
- G_OBJECT_CLASS(g_pyarch_instruction_parent_class)->finalize(G_OBJECT(instr));
+ g_object_set_qdata_full(G_OBJECT(instr), cache_key, strdup(keyword), g_free);
+
+ g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(instr), uid);
+
+ return 0;
}
@@ -268,151 +209,21 @@ static void g_pyarch_instruction_finalize(GPyArchInstruction *instr)
* *
******************************************************************************/
-static const char *g_pyarch_instruction_get_keyword(GPyArchInstruction *instr)
+static const char *py_arch_instruction_get_class_keyword(GArchInstruction *instr)
{
const char *result; /* Désignation à retourner */
+ GQuark cache_key; /* Emplacement local */
- result = instr->cached_keyword;
+ cache_key = get_cached_keyword_quark();
- return result;
-
-}
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GLUE POUR CREATION DEPUIS PYTHON */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type du nouvel objet à mettre en place. *
-* args = éventuelle liste d'arguments. *
-* kwds = éventuel dictionnaire de valeurs mises à disposition. *
-* *
-* Description : Accompagne la création d'une instance dérivée en Python. *
-* *
-* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_arch_instruction_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Objet à retourner */
- PyTypeObject *base; /* Type de base à dériver */
- bool first_time; /* Evite les multiples passages*/
- GType gtype; /* Nouveau type de processeur */
- bool status; /* Bilan d'un enregistrement */
-
- /* Validations diverses */
-
- base = get_python_arch_instruction_type();
-
- if (type == base)
- {
- result = NULL;
- PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
- goto exit;
- }
-
- /* Mise en place d'un type dédié */
-
- first_time = (g_type_from_name(type->tp_name) == 0);
-
- gtype = build_dynamic_type(G_TYPE_PYARCH_INSTRUCTION, type->tp_name,
- (GClassInitFunc)py_arch_instruction_init_gclass, NULL, NULL);
-
- if (first_time)
- {
- status = register_class_for_dynamic_pygobject(gtype, type, base);
-
- if (!status)
- {
- result = NULL;
- goto exit;
- }
-
- }
-
- /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
-
- result = PyType_GenericNew(type, args, kwds);
-
- exit:
+ result = g_object_get_qdata(G_OBJECT(instr), cache_key);
+ assert(result != NULL);
return result;
}
-/******************************************************************************
-* *
-* Paramètres : class = classe à initialiser. *
-* unused = données non utilisées ici. *
-* *
-* Description : Initialise la classe générique des instructions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void py_arch_instruction_init_gclass(GPyArchInstructionClass *class, gpointer unused)
-{
- /// ....
-
-}
-
-
-/******************************************************************************
-* *
-* 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_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- unsigned short int uid; /* Indentifiant unique de type */
- const char *keyword; /* Désignation d'instruction */
- int ret; /* Bilan de lecture des args. */
- GPyArchInstruction *instr; /* Instruction à manipuler */
-
- static char *kwlist[] = { "uid", "keyword", NULL };
-
- /* Récupération des paramètres */
-
- ret = PyArg_ParseTupleAndKeywords(args, kwds, "Hs", kwlist, &uid, &keyword);
- if (!ret) return -1;
-
- /* Initialisation d'un objet GLib */
-
- ret = forward_pygobjet_init(self);
- if (ret == -1) return -1;
-
- /* Eléments de base */
-
- instr = G_PYARCH_INSTRUCTION(pygobject_get(self));
-
- instr->cached_keyword = strdup(keyword);
-
- g_arch_instruction_set_unique_id(G_ARCH_INSTRUCTION(instr), uid);
-
- return 0;
-
-}
-
-
/* ---------------------------------------------------------------------------------- */
/* MANIPULATION DES OPERANDES */
@@ -1085,8 +896,7 @@ bool ensure_python_arch_instruction_is_registered(void)
if (!ensure_python_line_generator_is_registered())
return false;
- if (!_register_class_for_pygobject(dict, G_TYPE_PYARCH_INSTRUCTION, type,
- &PyGObject_Type, get_python_line_generator_type(), NULL))
+ if (!register_class_for_pygobject(dict, G_TYPE_ARCH_INSTRUCTION, type))
return false;
if (!define_arch_instruction_constants(type))
diff --git a/plugins/pychrysalide/arch/instructions/Makefile.am b/plugins/pychrysalide/arch/instructions/Makefile.am
index 4c36acf..65efe42 100644
--- a/plugins/pychrysalide/arch/instructions/Makefile.am
+++ b/plugins/pychrysalide/arch/instructions/Makefile.am
@@ -2,24 +2,15 @@
noinst_LTLIBRARIES = libpychrysaarchinstructions.la
libpychrysaarchinstructions_la_SOURCES = \
- constants.h constants.c \
- module.h module.c \
- raw.h raw.c \
+ constants.h constants.c \
+ module.h module.c \
+ raw.h raw.c \
undefined.h undefined.c
-libpychrysaarchinstructions_la_LIBADD =
-
-libpychrysaarchinstructions_la_LDFLAGS =
+libpychrysaarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaarchinstructions_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/arch/instructions/raw.c b/plugins/pychrysalide/arch/instructions/raw.c
index c1366c6..7e58b96 100644
--- a/plugins/pychrysalide/arch/instructions/raw.c
+++ b/plugins/pychrysalide/arch/instructions/raw.c
@@ -99,7 +99,7 @@ static PyObject *py_raw_instruction_new(PyTypeObject *type, PyObject *args, PyOb
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -458,7 +458,7 @@ bool ensure_python_raw_instruction_is_registered(void)
if (!ensure_python_arch_instruction_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_RAW_INSTRUCTION, type, get_python_arch_instruction_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_RAW_INSTRUCTION, type))
return false;
if (!define_raw_instruction_constants(type))
diff --git a/plugins/pychrysalide/arch/instructions/undefined.c b/plugins/pychrysalide/arch/instructions/undefined.c
index 5741609..1246daa 100644
--- a/plugins/pychrysalide/arch/instructions/undefined.c
+++ b/plugins/pychrysalide/arch/instructions/undefined.c
@@ -88,7 +88,7 @@ static PyObject *py_undef_instruction_new(PyTypeObject *type, PyObject *args, Py
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -130,7 +130,7 @@ static int py_undef_instruction_init(PyObject *self, PyObject *args, PyObject *k
unsigned long behavior; /* Conséquence pour l'instruct°*/
int ret; /* Bilan de lecture des args. */
GUndefInstruction *instr; /* Instruction à manipuler */
- undef_obj_extra *extra; /* Données insérées à modifier */
+ undef_extra_data_t *extra; /* Données insérées à modifier */
static char *kwlist[] = { "behavior", NULL };
@@ -285,7 +285,7 @@ bool ensure_python_undefined_instruction_is_registered(void)
if (!ensure_python_arch_instruction_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_UNDEF_INSTRUCTION, type, get_python_arch_instruction_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_UNDEF_INSTRUCTION, type))
return false;
if (!define_undefined_instruction_constants(type))
diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c
index 7fa5118..0aee4f7 100644
--- a/plugins/pychrysalide/arch/operand.c
+++ b/plugins/pychrysalide/arch/operand.c
@@ -35,6 +35,7 @@
#include "../access.h"
#include "../helpers.h"
+#include "../glibext/singleton.h"
@@ -48,7 +49,7 @@ static PyObject *py_arch_operand_new(PyTypeObject *, PyObject *, PyObject *);
static void py_arch_operand_init_gclass(GArchOperandClass *, gpointer);
/* Compare un opérande avec un autre. */
-static int py_arch_operand___cmp___wrapper(const GArchOperand *, const GArchOperand *);
+static int py_arch_operand___cmp___wrapper(const GArchOperand *, const GArchOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand *, const GArchOperand *);
@@ -59,9 +60,13 @@ static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const G
/* Traduit un opérande en version humainement lisible. */
static void py_arch_operand_print_wrapper(const GArchOperand *, GBufferLine *);
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Construit un petit résumé concis de l'opérande. */
static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const GLoadedBinary *);
+#endif
+
/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */
@@ -144,7 +149,7 @@ static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObjec
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -185,15 +190,18 @@ static void py_arch_operand_init_gclass(GArchOperandClass *class, gpointer unuse
class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper;
class->print = py_arch_operand_print_wrapper;
+#ifdef INCLUDE_GTK_SUPPORT
class->build_tooltip = py_arch_operand_build_tooltip_wrapper;
+#endif
}
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -203,7 +211,7 @@ static void py_arch_operand_init_gclass(GArchOperandClass *class, gpointer unuse
* *
******************************************************************************/
-static int py_arch_operand___cmp___wrapper(const GArchOperand *a, const GArchOperand *b)
+static int py_arch_operand___cmp___wrapper(const GArchOperand *a, const GArchOperand *b, bool lock)
{
int result; /* Empreinte à retourner */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
@@ -454,6 +462,9 @@ static void py_arch_operand_print_wrapper(const GArchOperand *operand, GBufferLi
}
+#ifdef INCLUDE_GTK_SUPPORT
+
+
/******************************************************************************
* *
* Paramètres : operand = opérande à consulter. *
@@ -520,6 +531,9 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand,
}
+#endif
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION D'OPERANDE QUELCONQUE */
@@ -558,7 +572,7 @@ static PyObject *py_arch_operand_richcompare(PyObject *a, PyObject *b, int op)
reg_a = G_ARCH_OPERAND(pygobject_get(a));
reg_b = G_ARCH_OPERAND(pygobject_get(b));
- status = py_arch_operand___cmp___wrapper(reg_a, reg_b);
+ status = py_arch_operand___cmp___wrapper(reg_a, reg_b, true);
result = status_to_rich_cmp_state(status, op);
@@ -707,7 +721,9 @@ PyTypeObject *get_python_arch_operand_type(void)
ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER,
ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER,
ARCH_OPERAND_PRINT_WRAPPER,
+#ifdef INCLUDE_GTK_SUPPORT
ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER,
+#endif
ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD,
ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD,
{ NULL }
@@ -768,7 +784,10 @@ bool ensure_python_arch_operand_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARCH_OPERAND, type, &PyGObject_Type))
+ if (!ensure_python_singleton_candidate_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ARCH_OPERAND, type))
return false;
}
diff --git a/plugins/pychrysalide/arch/operands/Makefile.am b/plugins/pychrysalide/arch/operands/Makefile.am
index 725096f..a41cbbb 100644
--- a/plugins/pychrysalide/arch/operands/Makefile.am
+++ b/plugins/pychrysalide/arch/operands/Makefile.am
@@ -1,30 +1,22 @@
noinst_LTLIBRARIES = libpychrysaarchoperands.la
-libpychrysaarchoperands_la_SOURCES = \
- constants.h constants.c \
- feeder.h feeder.c \
- immediate.h immediate.c \
- module.h module.c \
- proxy.h proxy.c \
- register.h register.c \
- rename.h rename.c \
- target.h target.c \
+libpychrysaarchoperands_la_SOURCES = \
+ constants.h constants.c \
+ feeder.h feeder.c \
+ immediate.h immediate.c \
+ known.h known.c \
+ module.h module.c \
+ proxy.h proxy.c \
+ register.h register.c \
+ rename.h rename.c \
+ target.h target.c \
targetable.h targetable.c
-libpychrysaarchoperands_la_LIBADD =
-
-libpychrysaarchoperands_la_LDFLAGS =
+libpychrysaarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaarchoperands_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/arch/operands/immediate.c b/plugins/pychrysalide/arch/operands/immediate.c
index 2634352..2239eb2 100644
--- a/plugins/pychrysalide/arch/operands/immediate.c
+++ b/plugins/pychrysalide/arch/operands/immediate.c
@@ -46,9 +46,6 @@
-/* ------------------------- OPERANDE POUR VALEUR IMMEDIATE ------------------------- */
-
-
/* Crée un nouvel objet Python de type 'ImmOperand'. */
static PyObject *py_imm_operand_new(PyTypeObject *, PyObject *, PyObject *);
@@ -64,18 +61,6 @@ static PyObject *py_imm_operand_get_size(PyObject *, void *);
/* Fournit la valeur portée par une opérande numérique. */
static PyObject *py_imm_operand_get_value(PyObject *, void *);
-/* Indique si l'affichage est complété avec des zéros. */
-static PyObject *py_imm_operand_get_default_padding(PyObject *self, void *);
-
-/* Précise si des zéro doivent compléter l'affichage ou non. */
-static int py_imm_operand_set_default_padding(PyObject *, PyObject *, void *);
-
-/* Indique si l'affichage est complété avec des zéros. */
-static PyObject *py_imm_operand_get_padding(PyObject *self, void *);
-
-/* Précise si des zéro doivent compléter l'affichage ou non. */
-static int py_imm_operand_set_padding(PyObject *, PyObject *, void *);
-
/* Indique le format textuel par défaut de la valeur. */
static PyObject *py_imm_operand_get_default_display(PyObject *, void *);
@@ -90,19 +75,6 @@ static int py_imm_operand_set_display(PyObject *, PyObject *, void *);
-/* ----------------------- REMPLACEMENT DE VALEURS IMMEDIATES ----------------------- */
-
-
-/* Crée un nouvel objet Python de type 'KnownImmOperand'. */
-static PyObject *py_known_imm_operand_new(PyTypeObject *, PyObject *, PyObject *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* OPERANDE POUR VALEUR IMMEDIATE */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
* Paramètres : type = type de l'objet à instancier. *
@@ -391,158 +363,6 @@ static PyObject *py_imm_operand_get_value(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Indique si l'affichage est complété avec des zéros. *
-* *
-* Retour : true si des zéro sont ajoutés à l'affichage, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_imm_operand_get_default_padding(PyObject *self, void *closure)
-{
- PyObject *result; /* Instance Python à retourner */
- GImmOperand *operand; /* Version GLib de l'opérande */
- bool padding; /* Bourrage en préfixe ? */
-
-#define IMM_OPERAND_DEFAULT_PADDING_ATTRIB PYTHON_GETSET_DEF_FULL \
-( \
- default_padding, py_imm_operand, \
- "Get or set the status of default padding with zeros in front of the" \
- " textual representation." \
- "\n" \
- "The status is a boolean value." \
-)
-
- operand = G_IMM_OPERAND(pygobject_get(self));
-
- padding = g_imm_operand_get_default_padding(operand);
-
- result = padding ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* value = valeur fournie à intégrer ou prendre en compte. *
-* closure = non utilisé ici. *
-* *
-* Description : Précise si des zéro doivent compléter l'affichage ou non. *
-* *
-* Retour : Bilan de l'opération pour Python. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int py_imm_operand_set_default_padding(PyObject *self, PyObject *value, void *closure)
-{
- bool padding; /* Bourrage en préfixe ? */
- GImmOperand *operand; /* Version GLib de l'opérande */
-
- if (!PyBool_Check(value))
- {
- PyErr_SetString(PyExc_TypeError, _("Invalid padding state"));
- return -1;
- }
-
- padding = (value == Py_True);
-
- operand = G_IMM_OPERAND(pygobject_get(self));
-
- g_imm_operand_set_default_padding(operand, padding);
-
- return 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Indique si l'affichage est complété avec des zéros. *
-* *
-* Retour : true si des zéro sont ajoutés à l'affichage, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_imm_operand_get_padding(PyObject *self, void *closure)
-{
- PyObject *result; /* Instance Python à retourner */
- GImmOperand *operand; /* Version GLib de l'opérande */
- bool padding; /* Bourrage en préfixe ? */
-
-#define IMM_OPERAND_PADDING_ATTRIB PYTHON_GETSET_DEF_FULL \
-( \
- padding, py_imm_operand, \
- "Get or set the status of padding with zeros in front of the" \
- " textual representation." \
- "\n" \
- "The status is a boolean value." \
-)
-
- operand = G_IMM_OPERAND(pygobject_get(self));
-
- padding = g_imm_operand_does_padding(operand);
-
- result = padding ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* value = valeur fournie à intégrer ou prendre en compte. *
-* closure = non utilisé ici. *
-* *
-* Description : Précise si des zéro doivent compléter l'affichage ou non. *
-* *
-* Retour : Bilan de l'opération pour Python. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int py_imm_operand_set_padding(PyObject *self, PyObject *value, void *closure)
-{
- bool padding; /* Bourrage en préfixe ? */
- GImmOperand *operand; /* Version GLib de l'opérande */
-
- if (!PyBool_Check(value))
- {
- PyErr_SetString(PyExc_TypeError, _("Invalid padding state"));
- return -1;
- }
-
- padding = (value == Py_True);
-
- operand = G_IMM_OPERAND(pygobject_get(self));
-
- g_imm_operand_pad(operand, padding);
-
- return 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
* Description : Indique le format textuel par défaut de la valeur. *
* *
* Retour : Format global d'un affichage de valeur. *
@@ -721,8 +541,6 @@ PyTypeObject *get_python_imm_operand_type(void)
static PyGetSetDef py_imm_operand_getseters[] = {
IMM_OPERAND_SIZE_ATTRIB,
IMM_OPERAND_VALUE_ATTRIB,
- IMM_OPERAND_DEFAULT_PADDING_ATTRIB,
- IMM_OPERAND_PADDING_ATTRIB,
IMM_OPERAND_DEFAULT_DISPLAY_ATTRIB,
IMM_OPERAND_DISPLAY_ATTRIB,
{ NULL }
@@ -785,7 +603,7 @@ bool ensure_python_imm_operand_is_registered(void)
if (!ensure_python_renameable_operand_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_IMM_OPERAND, type, get_python_arch_operand_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_IMM_OPERAND, type))
return false;
if (!define_imm_operand_constants(type))
@@ -841,189 +659,3 @@ int convert_to_imm_operand(PyObject *arg, void *dst)
return result;
}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* REMPLACEMENT DE VALEURS IMMEDIATES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type de l'objet à instancier. *
-* args = arguments fournis à l'appel. *
-* kwds = arguments de type key=val fournis. *
-* *
-* Description : Crée un nouvel objet Python de type 'KnownImmOperand'. *
-* *
-* Retour : Instance Python mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_known_imm_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Instance à retourner */
- GImmOperand *imm; /* Opérande à remplacer */
- const char *alt; /* Impression alternative */
- int ret; /* Bilan de lecture des args. */
- GArchOperand *operand; /* Création GLib à transmettre */
-
-#define KNOWN_IMM_OPERAND_DOC \
- "The KnownImmOperand provides replacement of" \
- " pychrysalide.arch.operands.ImmOperand instances by an alternative" \
- " text.\n" \
- "\n" \
- "Instances can be created using the following constructor:\n" \
- "\n" \
- " KnownImmOperand(imm, alt)" \
- "\n" \
- "Where imm is an operand of type pychrysalide.arch.operands.ImmOperand" \
- " and alt is a string providing the text to be rendered at object" \
- " display."
-
- ret = PyArg_ParseTuple(args, "O&s", convert_to_imm_operand, &imm, &alt);
- if (!ret) return NULL;
-
- operand = g_known_imm_operand_new(imm, alt);
-
- result = pygobject_new(G_OBJECT(operand));
-
- g_object_unref(operand);
-
- return (PyObject *)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_known_imm_operand_type(void)
-{
- static PyMethodDef py_known_imm_operand_methods[] = {
- { NULL }
- };
-
- static PyGetSetDef py_known_imm_operand_getseters[] = {
- { NULL }
- };
-
- static PyTypeObject py_known_imm_operand_type = {
-
- PyVarObject_HEAD_INIT(NULL, 0)
-
- .tp_name = "pychrysalide.arch.operands.KnownImmOperand",
- .tp_basicsize = sizeof(PyGObject),
-
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-
- .tp_doc = KNOWN_IMM_OPERAND_DOC,
-
- .tp_methods = py_known_imm_operand_methods,
- .tp_getset = py_known_imm_operand_getseters,
- .tp_new = py_known_imm_operand_new
-
- };
-
- return &py_known_imm_operand_type;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : module = module dont la définition est à compléter. *
-* *
-* Description : Prend en charge l'objet 'pychrysalide.arch.KnownImmOperand'. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool ensure_python_known_imm_operand_is_registered(void)
-{
- PyTypeObject *type; /* Type Python 'ImmOperand' */
- PyObject *module; /* Module à recompléter */
- PyObject *dict; /* Dictionnaire du module */
-
- type = get_python_known_imm_operand_type();
-
- if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
- {
- module = get_access_to_python_module("pychrysalide.arch.operands");
-
- dict = PyModule_GetDict(module);
-
- if (!ensure_python_imm_operand_is_registered())
- return false;
-
- if (!ensure_python_renamed_operand_is_registered())
- return false;
-
- if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_IMM_OPERAND, type, get_python_imm_operand_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 remplaçant d'opérande d'immédiat. *
-* *
-* Retour : Bilan de l'opération, voire indications supplémentaires. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int convert_to_known_imm_operand(PyObject *arg, void *dst)
-{
- int result; /* Bilan à retourner */
-
- result = PyObject_IsInstance(arg, (PyObject *)get_python_known_imm_operand_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 known immediate operand");
- break;
-
- case 1:
- *((GKnownImmOperand **)dst) = G_KNOWN_IMM_OPERAND(pygobject_get(arg));
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- return result;
-
-}
diff --git a/plugins/pychrysalide/arch/operands/immediate.h b/plugins/pychrysalide/arch/operands/immediate.h
index 15d2c3e..4a1e6de 100644
--- a/plugins/pychrysalide/arch/operands/immediate.h
+++ b/plugins/pychrysalide/arch/operands/immediate.h
@@ -31,9 +31,6 @@
-/* ------------------------- OPERANDE POUR VALEUR IMMEDIATE ------------------------- */
-
-
/* Fournit un accès à une définition de type à diffuser. */
PyTypeObject *get_python_imm_operand_type(void);
@@ -45,18 +42,4 @@ int convert_to_imm_operand(PyObject *, void *);
-/* ----------------------- REMPLACEMENT DE VALEURS IMMEDIATES ----------------------- */
-
-
-/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_known_imm_operand_type(void);
-
-/* Prend en charge l'objet 'pychrysalide.arch.KnownImmOperand'. */
-bool ensure_python_known_imm_operand_is_registered(void);
-
-/* Tente de convertir en remplaçant d'opérande d'immédiat. */
-int convert_to_known_imm_operand(PyObject *, void *);
-
-
-
#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_IMMEDIATE_H */
diff --git a/plugins/pychrysalide/arch/operands/known.c b/plugins/pychrysalide/arch/operands/known.c
new file mode 100644
index 0000000..fab426e
--- /dev/null
+++ b/plugins/pychrysalide/arch/operands/known.c
@@ -0,0 +1,224 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * known.c - équivalent Python du fichier "arch/operands/known.h"
+ *
+ * Copyright (C) 2020 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 "known.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <arch/operands/known.h>
+
+
+#include "immediate.h"
+#include "rename.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+/* Crée un nouvel objet Python de type 'KnownImmOperand'. */
+static PyObject *py_known_imm_operand_new(PyTypeObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'KnownImmOperand'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_known_imm_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Instance à retourner */
+ GImmOperand *imm; /* Opérande à remplacer */
+ const char *alt; /* Impression alternative */
+ int ret; /* Bilan de lecture des args. */
+ GArchOperand *operand; /* Création GLib à transmettre */
+
+#define KNOWN_IMM_OPERAND_DOC \
+ "The KnownImmOperand provides replacement of" \
+ " pychrysalide.arch.operands.ImmOperand instances by an alternative" \
+ " text.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " KnownImmOperand(imm, alt)" \
+ "\n" \
+ "Where imm is an operand of type pychrysalide.arch.operands.ImmOperand" \
+ " and alt is a string providing the text to be rendered at object" \
+ " display."
+
+ ret = PyArg_ParseTuple(args, "O&s", convert_to_imm_operand, &imm, &alt);
+ if (!ret) return NULL;
+
+ operand = g_known_imm_operand_new(imm, alt);
+
+ result = pygobject_new(G_OBJECT(operand));
+
+ g_object_unref(operand);
+
+ return (PyObject *)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_known_imm_operand_type(void)
+{
+ static PyMethodDef py_known_imm_operand_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_known_imm_operand_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_known_imm_operand_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.arch.operands.KnownImmOperand",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KNOWN_IMM_OPERAND_DOC,
+
+ .tp_methods = py_known_imm_operand_methods,
+ .tp_getset = py_known_imm_operand_getseters,
+ .tp_new = py_known_imm_operand_new
+
+ };
+
+ return &py_known_imm_operand_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.arch.KnownImmOperand'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_known_imm_operand_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ImmOperand' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_known_imm_operand_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.arch.operands");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_imm_operand_is_registered())
+ return false;
+
+ if (!ensure_python_renamed_operand_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_IMM_OPERAND, 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 remplaçant d'opérande d'immédiat. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_known_imm_operand(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_known_imm_operand_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 known immediate operand");
+ break;
+
+ case 1:
+ *((GKnownImmOperand **)dst) = G_KNOWN_IMM_OPERAND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/arch/operands/known.h b/plugins/pychrysalide/arch/operands/known.h
new file mode 100644
index 0000000..b5ced68
--- /dev/null
+++ b/plugins/pychrysalide/arch/operands/known.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * known.h - prototypes pour l'équivalent Python du fichier "arch/operands/known.h"
+ *
+ * Copyright (C) 2020 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_PYCHRYSALIDE_ARCH_OPERANDS_KNOWN_H
+#define _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_KNOWN_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_known_imm_operand_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.arch.KnownImmOperand'. */
+bool ensure_python_known_imm_operand_is_registered(void);
+
+/* Tente de convertir en remplaçant d'opérande d'immédiat. */
+int convert_to_known_imm_operand(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_KNOWN_H */
diff --git a/plugins/pychrysalide/arch/operands/module.c b/plugins/pychrysalide/arch/operands/module.c
index f1669fb..89adecc 100644
--- a/plugins/pychrysalide/arch/operands/module.c
+++ b/plugins/pychrysalide/arch/operands/module.c
@@ -30,6 +30,7 @@
#include "feeder.h"
#include "immediate.h"
+#include "known.h"
#include "proxy.h"
#include "register.h"
#include "rename.h"
diff --git a/plugins/pychrysalide/arch/operands/proxy.c b/plugins/pychrysalide/arch/operands/proxy.c
index 1cfd4a4..5009d29 100644
--- a/plugins/pychrysalide/arch/operands/proxy.c
+++ b/plugins/pychrysalide/arch/operands/proxy.c
@@ -105,7 +105,7 @@ static PyObject *py_proxy_operand_new(PyTypeObject *type, PyObject *args, PyObje
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -319,7 +319,10 @@ bool ensure_python_proxy_operand_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PROXY_OPERAND, type, get_python_arch_operand_type()))
+ if (!ensure_python_arch_operand_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PROXY_OPERAND, type))
return false;
}
diff --git a/plugins/pychrysalide/arch/operands/register.c b/plugins/pychrysalide/arch/operands/register.c
index fcf838c..2a48a0f 100644
--- a/plugins/pychrysalide/arch/operands/register.c
+++ b/plugins/pychrysalide/arch/operands/register.c
@@ -67,9 +67,6 @@ static PyObject *py_register_operand__print(PyObject *, PyObject *);
/* Fournit le registre associé à l'opérande. */
static PyObject *py_register_operand_get_register(PyObject *, void *);
-/* Indique le type d'accès réalisé sur l'opérande. */
-static PyObject *py_register_operand_is_written(PyObject *, void *);
-
/* ---------------------------------------------------------------------------------- */
@@ -115,7 +112,7 @@ static PyObject *py_register_operand_new(PyTypeObject *type, PyObject *args, PyO
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -357,43 +354,6 @@ static PyObject *py_register_operand_get_register(PyObject *self, void *closure)
/******************************************************************************
* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Indique le type d'accès réalisé sur l'opérande. *
-* *
-* Retour : Type d'accès : True en cas d'écriture, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_register_operand_is_written(PyObject *self, void *closure)
-{
- PyObject *result; /* Résultat à retourner */
- GRegisterOperand *operand; /* Version GLib du type */
- bool status; /* Statut de la ligne */
-
-#define REGISTER_OPERAND_IS_WRITTEN_ATTRIB PYTHON_IS_DEF_FULL \
-( \
- written, py_register_operand, \
- "Kind of access for the register when its instruction is executed." \
-)
-
- operand = G_REGISTER_OPERAND(pygobject_get(self));
-
- status = g_register_operand_is_written(operand);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -414,7 +374,6 @@ PyTypeObject *get_python_register_operand_type(void)
static PyGetSetDef py_register_operand_getseters[] = {
REGISTER_OPERAND_REGISTER_ATTRIB,
- REGISTER_OPERAND_IS_WRITTEN_ATTRIB,
{ NULL }
};
@@ -468,7 +427,10 @@ bool ensure_python_register_operand_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_REGISTER_OPERAND, type, get_python_arch_operand_type()))
+ if (!ensure_python_arch_operand_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_REGISTER_OPERAND, type))
return false;
}
diff --git a/plugins/pychrysalide/arch/operands/target.c b/plugins/pychrysalide/arch/operands/target.c
index 5cd9f59..b8cd536 100644
--- a/plugins/pychrysalide/arch/operands/target.c
+++ b/plugins/pychrysalide/arch/operands/target.c
@@ -115,7 +115,7 @@ static PyObject *py_target_operand_new(PyTypeObject *type, PyObject *args, PyObj
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -176,7 +176,8 @@ static int py_target_operand_init(PyObject *self, PyObject *args, PyObject *kwds
MemoryDataSize size; /* Taille des adresses mémoire */
vmpa2t *addr; /* Emplacement de symbole */
int ret; /* Bilan de lecture des args. */
- GTargetOperand *operand; /* Opérande à manipuler */
+ GTargetOperand *operand; /* Opérande à manipuler */
+ tarop_extra_data_t *extra; /* Données insérées à modifier */
#define TARGET_OPERAND_DOC \
"The TargetOperand object translates immediate values as symbols.\n" \
@@ -203,7 +204,10 @@ static int py_target_operand_init(PyObject *self, PyObject *args, PyObject *kwds
operand = G_TARGET_OPERAND(pygobject_get(self));
- operand->size = size;
+ extra = GET_TARGET_OP_EXTRA(operand);
+
+ extra->size = size;
+
copy_vmpa(&operand->addr, addr);
clean_vmpa_arg(addr);
@@ -425,10 +429,13 @@ bool ensure_python_target_operand_is_registered(void)
dict = PyModule_GetDict(module);
+ if (!ensure_python_arch_operand_is_registered())
+ return false;
+
if (!ensure_python_targetable_operand_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_TARGET_OPERAND, type, get_python_arch_operand_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_TARGET_OPERAND, type))
return false;
}
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 80b55d3..00b472f 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -186,7 +186,7 @@ static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObj
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -1452,7 +1452,7 @@ bool ensure_python_arch_processor_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARCH_PROCESSOR, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_ARCH_PROCESSOR, type))
return false;
if (!define_arch_processor_constants(type))
diff --git a/plugins/pychrysalide/arch/register.c b/plugins/pychrysalide/arch/register.c
index 61da77f..615a5b7 100644
--- a/plugins/pychrysalide/arch/register.c
+++ b/plugins/pychrysalide/arch/register.c
@@ -36,6 +36,7 @@
#include "../access.h"
#include "../helpers.h"
+#include "../analysis/storage/serialize.h"
@@ -143,7 +144,7 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -682,7 +683,10 @@ bool ensure_python_arch_register_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_ARCH_REGISTER, type, &PyGObject_Type))
+ if (!ensure_python_serializable_object_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ARCH_REGISTER, type))
return false;
}
diff --git a/plugins/pychrysalide/common/Makefile.am b/plugins/pychrysalide/common/Makefile.am
index 1fb268d..b5249b9 100644
--- a/plugins/pychrysalide/common/Makefile.am
+++ b/plugins/pychrysalide/common/Makefile.am
@@ -1,25 +1,21 @@
noinst_LTLIBRARIES = libpychrysacommon.la
-libpychrysacommon_la_SOURCES = \
- bits.h bits.c \
- fnv1a.h fnv1a.c \
- hex.h hex.c \
- leb128.h leb128.c \
- module.h module.c \
- packed.h packed.c \
- pathname.h pathname.c \
+libpychrysacommon_la_SOURCES = \
+ bits.h bits.c \
+ fnv1a.h fnv1a.c \
+ hex.h hex.c \
+ itoa.h itoa.c \
+ leb128.h leb128.c \
+ module.h module.c \
+ packed.h packed.c \
+ pathname.h pathname.c \
pearson.h pearson.c
-libpychrysacommon_la_LDFLAGS =
+libpychrysacommon_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysacommon_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/common/bits.c b/plugins/pychrysalide/common/bits.c
index 73fd55b..a127251 100644
--- a/plugins/pychrysalide/common/bits.c
+++ b/plugins/pychrysalide/common/bits.c
@@ -65,6 +65,9 @@ static PyObject *py_bitfield_richcompare(PyObject *, PyObject *, int);
/* Crée une copie d'un champ de bits classique. */
static PyObject *py_bitfield_dup(PyObject *, PyObject *);
+/* Redimensionne un champ de bits. */
+static PyObject *py_bitfield_resize(PyObject *, PyObject *);
+
/* Bascule à 0 un champ de bits dans son intégralité. */
static PyObject *py_bitfield_reset_all(PyObject *, PyObject *);
@@ -77,6 +80,9 @@ static PyObject *py_bitfield_reset(PyObject *, PyObject *);
/* Bascule à 1 une partie d'un champ de bits. */
static PyObject *py_bitfield_set(PyObject *, PyObject *);
+/* Réalise une opération OU logique entre deux champs de bits. */
+static PyObject *py_bitfield_or_at(PyObject *, PyObject *);
+
/* Détermine si un bit est à 1 dans un champ de bits. */
static PyObject *py_bitfield_test(PyObject *, PyObject *);
@@ -86,6 +92,15 @@ static PyObject *py_bitfield_test_none(PyObject *, PyObject *);
/* Détermine si un ensemble de bits est à 1 dans un champ. */
static PyObject *py_bitfield_test_all(PyObject *, PyObject *);
+/* Teste l'état à 0 de bits selon un masque de bits. */
+static PyObject *py_bitfield_test_zeros_with(PyObject *, PyObject *);
+
+/* Teste l'état à 1 de bits selon un masque de bits. */
+static PyObject *py_bitfield_test_ones_with(PyObject *, PyObject *);
+
+/* Recherche un prochain bit défini dans un champ de bits. */
+static PyObject *py_bitfield_find_next_set(PyObject *, PyObject *);
+
/* Indique la taille d'un champ de bits donné. */
static PyObject *py_bitfield_get_size(PyObject *, void *);
@@ -399,6 +414,47 @@ static PyObject *py_bitfield_dup(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : self = champ de bits à dupliquer. *
+* args = non utilisé ici. *
+* *
+* Description : Redimensionne un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_resize(PyObject *self, PyObject *args)
+{
+ unsigned long length; /* Nouvelle taille à respecter */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+#define BITFIELD_RESIZE_METHOD PYTHON_METHOD_DEF \
+( \
+ resize, "$self, length, /", \
+ METH_VARARGS, py_bitfield, \
+ "Resize a bitfield and fix its new size to *length*.\n" \
+ "\n" \
+ "The new bits get initialized to the same state used at the" \
+ " bitfield creation." \
+)
+
+ ret = PyArg_ParseTuple(args, "k", &length);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ resize_bit_field(&bf->native, length);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = champ de bits à modifier. *
* args = non utilisé ici. *
* *
@@ -552,6 +608,49 @@ static PyObject *py_bitfield_set(PyObject *self, PyObject *args)
* Paramètres : self = champ de bits à consulter. *
* args = arguments fournis pour la conduite de l'opération. *
* *
+* Description : Réalise une opération OU logique entre deux champs de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_or_at(PyObject *self, PyObject *args)
+{
+ bitfield_t *src; /* Seconde champ de bits */
+ unsigned long first; /* Indice du premier bit testé */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+#define BITFIELD_OR_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ or_at, "$self, src, first, /", \
+ METH_VARARGS, py_bitfield, \
+ "Perform an OR operation with another bitfield.\n" \
+ "\n" \
+ "The *src* argument is expected to be another" \
+ " pychrysalide.common.BitField instance. The area to" \
+ " process starts at bit *first* from *src*." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&k", convert_to_bitfield, &src, &first);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ or_bit_field_at(bf->native, src, first);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
* Description : Détermine si un bit est à 1 dans un champ de bits. *
* *
* Retour : true si le bit correspondant est à l'état haut. *
@@ -695,6 +794,158 @@ static PyObject *py_bitfield_test_all(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Teste l'état à 0 de bits selon un masque de bits. *
+* *
+* Retour : true si les bits visés sont à l'état bas. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_zeros_with(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long first; /* Indice du premier bit testé */
+ bitfield_t *mask; /* Champ de bits natif */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+#define BITFIELD_TEST_ZEROS_WITH_METHOD PYTHON_METHOD_DEF \
+( \
+ test_zeros_with, "$self, first, mask, /", \
+ METH_VARARGS, py_bitfield, \
+ "Test a range of bits against another bit field.\n" \
+ "\n" \
+ "The area to process starts at bit *first* and the" \
+ " test relies on bits set within the *mask* object.\n" \
+ "\n" \
+ "The result is a boolean value: True if all tested" \
+ " bits are unset, False otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "kO&", &first, convert_to_bitfield, &mask);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_zeros_within_bit_field(bf->native, first, mask);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Teste l'état à 1 de bits selon un masque de bits. *
+* *
+* Retour : true si les bits visés sont à l'état haut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_ones_with(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long first; /* Indice du premier bit testé */
+ bitfield_t *mask; /* Champ de bits natif */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+#define BITFIELD_TEST_ONES_WITH_METHOD PYTHON_METHOD_DEF \
+( \
+ test_ones_with, "$self, first, mask, /", \
+ METH_VARARGS, py_bitfield, \
+ "Test a range of bits against another bit field.\n" \
+ "\n" \
+ "The area to process starts at bit *first* and the" \
+ " test relies on bits set within the *mask* object.\n" \
+ "\n" \
+ "The result is a boolean value: True if all tested" \
+ " bits are set, False otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "kO&", &first, convert_to_bitfield, &mask);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_ones_within_bit_field(bf->native, first, mask);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Recherche un prochain bit défini dans un champ de bits. *
+* *
+* Retour : Position d'un bit à 1 ou taille du champ si plus aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_find_next_set(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long prev; /* Indice d'un bit à écarter */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ size_t found; /* Indice de bit trouvé */
+
+#define BITFIELD_FIND_NEXT_SET_METHOD PYTHON_METHOD_DEF \
+( \
+ find_next_set, "$self, /, prev=None", \
+ METH_VARARGS, py_bitfield, \
+ "Find the index of the next set bit in the bit field.\n"\
+ "\n" \
+ "If provided, the *prev* argument is the position of" \
+ " a previously found bit, which gets discarded for the" \
+ " current call.\n" \
+ "\n" \
+ "The result is a integer value: a valid index inside" \
+ " the bit field, or the bit field size if no set bit" \
+ " is found." \
+)
+
+ prev = (unsigned long)-1;
+
+ ret = PyArg_ParseTuple(args, "|k", &prev);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ found = find_next_set_in_bit_field(bf->native, prev == (unsigned long)-1 ? NULL : (size_t []) { prev });
+
+ result = PyLong_FromSize_t(found);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = classe représentant une instruction. *
* closure = adresse non utilisée ici. *
* *
@@ -791,13 +1042,18 @@ PyTypeObject *get_python_bitfield_type(void)
static PyMethodDef py_bitfield_methods[] = {
BITFIELD_DUP_METHOD,
+ BITFIELD_RESIZE_METHOD,
BITFIELD_RESET_ALL_METHOD,
BITFIELD_SET_ALL_METHOD,
BITFIELD_RESET_METHOD,
BITFIELD_SET_METHOD,
+ BITFIELD_OR_AT_METHOD,
BITFIELD_TEST_METHOD,
BITFIELD_TEST_NONE_METHOD,
BITFIELD_TEST_ALL_METHOD,
+ BITFIELD_TEST_ZEROS_WITH_METHOD,
+ BITFIELD_TEST_ONES_WITH_METHOD,
+ BITFIELD_FIND_NEXT_SET_METHOD,
{ NULL }
};
@@ -876,6 +1132,51 @@ bool ensure_python_bitfield_is_registered(void)
/******************************************************************************
* *
+* 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 champ de bits. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_bitfield(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_bitfield_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 bit field");
+ break;
+
+ case 1:
+ *((bitfield_t **)dst) = ((py_bitfield_t *)arg)->native;
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : field = structure interne à copier en objet Python. *
* *
* Description : Convertit une structure de type 'bitfield_t' en objet Python.*
diff --git a/plugins/pychrysalide/common/bits.h b/plugins/pychrysalide/common/bits.h
index 6ddaaa5..804c3b5 100644
--- a/plugins/pychrysalide/common/bits.h
+++ b/plugins/pychrysalide/common/bits.h
@@ -40,6 +40,9 @@ PyTypeObject *get_python_bitfield_type(void);
/* Prend en charge l'objet 'pychrysalide.common.BitField'. */
bool ensure_python_bitfield_is_registered(void);
+/* Tente de convertir en champ de bits. */
+int convert_to_bitfield(PyObject *, void *);
+
/* Convertit une structure de type 'bitfield_t' en objet Python. */
PyObject *build_from_internal_bitfield(const bitfield_t *);
diff --git a/plugins/pychrysalide/common/itoa.c b/plugins/pychrysalide/common/itoa.c
new file mode 100644
index 0000000..107b047
--- /dev/null
+++ b/plugins/pychrysalide/common/itoa.c
@@ -0,0 +1,124 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * itoa.c - équivalent Python du fichier "common/itoa.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "itoa.h"
+
+
+#include <common/itoa.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+
+
+
+/* Détermine l'empreinte Itoa d'une chaîne de caractères. */
+static PyObject *py_itoa(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = NULL car méthode statique. *
+* args = arguments fournis lors de l'appel à la fonction. *
+* *
+* Description : Convertit une valeur en une forme textuelle. *
+* *
+* Retour : Chaîne de caractères mises en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_itoa(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ long long n; /* Valeur à transformer */
+ unsigned char base; /* Base de travail */
+ int ret; /* Bilan de lecture des args. */
+ char *strval; /* Valeur sous forme de chaîne */
+
+#define ITOA_METHOD PYTHON_METHOD_DEF \
+( \
+ itoa, "n, /, base=10", \
+ METH_VARARGS, py, \
+ "Construct a string representation of an integer *n* according" \
+ " to a given *base*.\n" \
+ "\n" \
+ "Both arguments are expected to be integer values; the result" \
+ " is a string or None in case of failure." \
+)
+
+ base = 10;
+
+ ret = PyArg_ParseTuple(args, "L|b", &n, &base);
+ if (!ret) return NULL;
+
+ strval = itoa(n, base);
+
+ if (strval != NULL)
+ {
+ result = PyUnicode_FromString(strval);
+ free(strval);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Définit une extension du module 'common' à compléter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_common_module_with_itoa(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Module à recompléter */
+
+ static PyMethodDef py_itoa_methods[] = {
+ ITOA_METHOD,
+ { NULL }
+ };
+
+ module = get_access_to_python_module("pychrysalide.common");
+
+ result = register_python_module_methods(module, py_itoa_methods);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/common/itoa.h b/plugins/pychrysalide/common/itoa.h
new file mode 100644
index 0000000..a66e767
--- /dev/null
+++ b/plugins/pychrysalide/common/itoa.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * itoa.h - prototypes pour l'équivalent Python du fichier "common/itoa.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_COMMON_ITOA_H
+#define _PLUGINS_PYCHRYSALIDE_COMMON_ITOA_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'common' à compléter. */
+bool populate_common_module_with_itoa(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_COMMON_ITOA_H */
diff --git a/plugins/pychrysalide/common/module.c b/plugins/pychrysalide/common/module.c
index 6ced1b7..a0042ee 100644
--- a/plugins/pychrysalide/common/module.c
+++ b/plugins/pychrysalide/common/module.c
@@ -28,6 +28,7 @@
#include "bits.h"
#include "fnv1a.h"
#include "hex.h"
+#include "itoa.h"
#include "leb128.h"
#include "packed.h"
#include "pathname.h"
@@ -99,6 +100,7 @@ bool populate_common_module(void)
if (result) result = populate_common_module_with_fnv1a();
if (result) result = populate_common_module_with_hex();
+ if (result) result = populate_common_module_with_itoa();
if (result) result = populate_common_module_with_leb128();
if (result) result = populate_common_module_with_pathname();
if (result) result = populate_common_module_with_pearson();
diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c
index 98f94b6..08f570f 100644
--- a/plugins/pychrysalide/core.c
+++ b/plugins/pychrysalide/core.c
@@ -21,6 +21,11 @@
*/
+#undef NO_IMPORT_PYGOBJECT
+#include <pygobject.h>
+#define NO_IMPORT_PYGOBJECT
+
+
#include "core.h"
@@ -35,7 +40,6 @@
#include <unistd.h>
-#include <config.h>
#include <i18n.h>
#include <gleak.h>
#include <common/cpp.h>
@@ -60,8 +64,10 @@
#include "debug/module.h"
#include "format/module.h"
#include "glibext/module.h"
-#include "gtkext/module.h"
-#include "gui/module.h"
+#ifdef INCLUDE_GTK_SUPPORT
+# include "gtkext/module.h"
+# include "gui/module.h"
+#endif
#include "mangling/module.h"
#include "plugins/module.h"
#include "plugins/plugin.h"
@@ -80,9 +86,6 @@ static bool _standalone = true;
/* Réceptacle pour le chargement forcé */
static PyObject *_chrysalide_module = NULL;
-/* Conservation des informations du thread principal */
-static PyThreadState *_main_tstate = NULL;
-
/* Fournit la révision du programme global. */
static PyObject *py_chrysalide_revision(PyObject *, PyObject *);
@@ -96,8 +99,13 @@ static PyObject *py_chrysalide_mod_version(PyObject *, PyObject *);
/* Détermine si l'interpréteur lancé est celui pris en compte. */
static bool is_current_abi_suitable(void);
+/* Assure une pleine initialisation des objets de Python-GI. */
+static bool install_metaclass_for_python_gobjects(void);
+
/* Définit la version attendue de GTK à charger dans Python. */
+#ifdef INCLUDE_GTK_SUPPORT
static bool set_version_for_gtk_namespace(const char *);
+#endif
/* Point de sortie pour l'initialisation de Python. */
static void PyExit_pychrysalide(void);
@@ -249,7 +257,8 @@ static bool is_current_abi_suitable(void)
#define GRAB_ABI_FLAGS_IN_PYTHON \
"import sys" "\n" \
"import os" "\n" \
- "os.write(%d, bytes(sys.abiflags, 'UTF-8'))" "\n"
+ "data = bytes(sys.abiflags, 'UTF-8') + b'\\0'" "\n" \
+ "os.write(%d, data)" "\n"
result = false;
@@ -289,6 +298,126 @@ static bool is_current_abi_suitable(void)
/******************************************************************************
* *
+* Paramètres : - *
+* *
+* Description : Assure une pleine initialisation des objets de Python-GI. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool install_metaclass_for_python_gobjects(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *gi_types_mod; /* Module Python-GObject */
+
+ /**
+ * Les extensions Python sont chargées à partir de la fonction load_python_plugins(),
+ * qui fait appel à create_python_plugin(). Une instance y est construite via un
+ * appel à PyObject_CallFunction() avec la classe spécifiée par l'alias AutoLoad
+ * dans le fichier __init__.py présent dans chaque module d'extension.
+ *
+ * Le constructeur py_plugin_module_new() renvoie in fine à la fonction générique
+ * python_abstract_constructor_with_dynamic_gtype(), laquelle conduit à la fonction
+ * pygobject_register_class() définie dans <python3-gi>/gi/pygobject-object.c.
+ * Le code de cette dernière comprend notamment la portion suivante :
+ *
+ * [...]
+ * Py_SET_TYPE(type, PyGObject_MetaType);
+ * [...]
+ * if (PyType_Ready(type) < 0) {
+ * g_warning ("couldn't make the type `%s' ready", type->tp_name);
+ * return;
+ * }
+ * [...]
+ *
+ * La fonction PyType_Ready() est définie dans <python3>/Objects/typeobject.c
+ * et commence par :
+ *
+ * int PyType_Ready(PyTypeObject *type)
+ * {
+ * if (type->tp_flags & Py_TPFLAGS_READY) {
+ * assert(_PyType_CheckConsistency(type));
+ * return 0;
+ * }
+ * [...]
+ * }
+ *
+ * La vérification de cohérencce commence par analyser le type et son propre
+ * type :
+ *
+ * - cf. _PyType_CheckConsistency() dans <python3>/Objects/typeobject.c :
+ *
+ * int _PyType_CheckConsistency(PyTypeObject *type)
+ * {
+ * [...]
+ * CHECK(!_PyObject_IsFreed((PyObject *)type));
+ * [...]
+ * }
+ *
+ * - cf. _PyObject_IsFreed() dans <python3>/Objects/object.c :
+ *
+ * int _PyObject_IsFreed(PyObject *op)
+ * {
+ * if (_PyMem_IsPtrFreed(op) || _PyMem_IsPtrFreed(Py_TYPE(op))) {
+ * return 1;
+ * }
+ *
+ * La fonction _PyMem_IsPtrFreed() recherche entre autres la valeur NULL.
+ *
+ * Or le type du type est écrasé dans la fonction pygobject_register_class()
+ * avec la valeur de la variable PyGObject_MetaType. Cette variable n'est
+ * définie qu'à un seul endroit, dans <python3-gi>/gi/gimodule.c :
+ *
+ * static PyObject *
+ * pyg__install_metaclass(PyObject *dummy, PyTypeObject *metaclass)
+ * {
+ * Py_INCREF(metaclass);
+ * PyGObject_MetaType = metaclass;
+ * Py_INCREF(metaclass);
+ *
+ * Py_SET_TYPE(&PyGObject_Type, metaclass);
+ *
+ * Py_INCREF(Py_None);
+ * return Py_None;
+ * }
+ *
+ * Afin de valider la vérification de _PyType_CheckConsistency() pour les
+ * modules externes qui entraînent un enregistrement tout en portant le drapeau
+ * Py_TPFLAGS_READY (typiquement ceux du répertoire "plugins/python/", il faut
+ * initialiser au besoin la variable PyGObject_MetaType.
+ *
+ * Une ligne suffit donc à enregistrer le type intermédiaire :
+ *
+ * from _gi import types
+ *
+ * On simule ici une déclaration similaire si nécessaire
+ */
+
+ result = false;
+
+ if (PyType_CheckExact(&PyGObject_Type))
+ {
+ gi_types_mod = PyImport_ImportModule("gi.types");
+
+ result = (PyErr_Occurred() == NULL);
+
+ if (result)
+ result = (PyType_CheckExact(&PyGObject_Type) == 0);
+
+ Py_XDECREF(gi_types_mod);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : version = idenfiant de la version de GTK à stipuler. *
* *
* Description : Définit la version attendue de GTK à charger dans Python. *
@@ -298,7 +427,7 @@ static bool is_current_abi_suitable(void)
* Remarques : - *
* *
******************************************************************************/
-
+#ifdef INCLUDE_GTK_SUPPORT
static bool set_version_for_gtk_namespace(const char *version)
{
bool result; /* Bilan à retourner */
@@ -334,6 +463,7 @@ static bool set_version_for_gtk_namespace(const char *version)
return result;
}
+#endif
/******************************************************************************
@@ -456,8 +586,13 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
goto exit;
}
+ if (!install_metaclass_for_python_gobjects())
+ goto exit;
+
+#ifdef INCLUDE_GTK_SUPPORT
if (!set_version_for_gtk_namespace("3.0"))
goto exit;
+#endif
if (!load_all_core_components(true))
{
@@ -482,8 +617,10 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
if (status) status = add_debug_module(result);
if (status) status = add_format_module(result);
if (status) status = add_glibext_module(result);
+#ifdef INCLUDE_GTK_SUPPORT
if (status) status = add_gtkext_module(result);
if (status) status = add_gui_module(result);
+#endif
if (status) status = add_mangling_module(result);
if (status) status = add_plugins_module(result);
@@ -497,8 +634,10 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
if (status) status = populate_debug_module();
if (status) status = populate_format_module();
if (status) status = populate_glibext_module();
+#ifdef INCLUDE_GTK_SUPPORT
if (status) status = populate_gtkext_module();
if (status) status = populate_gui_module();
+#endif
if (status) status = populate_mangling_module();
if (status) status = populate_plugins_module();
@@ -650,7 +789,6 @@ static void load_python_plugins(GPluginModule *plugin)
struct dirent *entry; /* Elément trouvé */
char *modname; /* Nom du module pour Python */
char *filename; /* Chemin d'accès reconstruit */
- PyThreadState *tstate; /* Contexte d'environnement */
GPluginModule *pyplugin; /* Lien vers un grffon Python */
bool status; /* Bilan d'une opération */
GGenConfig *config; /* Configuration à charger */
@@ -669,11 +807,11 @@ static void load_python_plugins(GPluginModule *plugin)
if (dir != NULL)
{
- closedir(dir);
+ closedir(dir);
- edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python");
- extend_python_path(edir);
- free(edir);
+ edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python");
+ extend_python_path(edir);
+ free(edir);
}
@@ -690,7 +828,7 @@ static void load_python_plugins(GPluginModule *plugin)
save = NULL; /* gcc... */
for (path = strtok_r(paths, ":", &save);
- path != NULL;
+ path != NULL;
path = strtok_r(NULL, ":", &save))
{
dir = opendir(path);
@@ -730,16 +868,7 @@ static void load_python_plugins(GPluginModule *plugin)
filename = stradd(filename, G_DIR_SEPARATOR_S);
filename = stradd(filename, entry->d_name);
- if (!_standalone)
- {
- tstate = get_pychrysalide_main_tstate();
- PyEval_RestoreThread(tstate);
- }
-
- pyplugin = g_python_plugin_new(modname, filename);
-
- if (!_standalone)
- PyEval_SaveThread();
+ pyplugin = create_python_plugin(modname, filename);
if (pyplugin == NULL)
{
@@ -778,7 +907,7 @@ static void load_python_plugins(GPluginModule *plugin)
}
- closedir(dir);
+ closedir(dir);
}
@@ -802,6 +931,7 @@ static void load_python_plugins(GPluginModule *plugin)
G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
int ret; /* Bilan de préparatifs */
_standalone = false;
@@ -819,9 +949,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
Py_Initialize();
- PyEval_InitThreads();
-
- PySys_SetArgv(0, (wchar_t *[]) { NULL });
+ gstate = PyGILState_Ensure();
_chrysalide_module = PyImport_ImportModule("pychrysalide");
@@ -838,9 +966,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
result = (_chrysalide_module != NULL);
- _main_tstate = PyThreadState_Get();
-
- PyEval_ReleaseLock();
+ PyGILState_Release(gstate);
cpi_done:
@@ -863,10 +989,16 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+
+ gstate = PyGILState_Ensure();
+
clear_all_accesses_to_python_modules();
Py_XDECREF(_chrysalide_module);
+ PyGILState_Release(gstate);
+
}
@@ -907,8 +1039,8 @@ static void free_native_plugin_type(PyTypeObject *type)
G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin, PluginAction action)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
size_t count; /* Quantité de greffons chargés*/
- PyTypeObject *parent; /* Type Python pour greffon */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
GPluginModule **list; /* Ensemble de ces greffons */
@@ -918,14 +1050,14 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin,
int ret; /* Bilan d'un appel */
PyTypeObject *type; /* Nouveau type dynamique */
+ gstate = PyGILState_Ensure();
+
if (action == PGA_NATIVE_PLUGINS_LOADED)
{
/* Intégration des greffons natifs en Python */
if (ensure_python_plugin_module_is_registered())
{
- parent = get_python_plugin_module_type();
-
module = get_access_to_python_module("pychrysalide.plugins");
assert(module != NULL);
@@ -958,7 +1090,7 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin,
type->tp_flags = Py_TPFLAGS_DEFAULT;
type->tp_new = no_python_constructor_allowed;
- if (register_class_for_pygobject(dict, G_OBJECT_TYPE(list[i]), type, parent))
+ if (register_class_for_pygobject(dict, G_OBJECT_TYPE(list[i]), type))
g_object_set_data_full(G_OBJECT(list[i]), "python_type", type,
(GDestroyNotify)free_native_plugin_type);
@@ -978,6 +1110,8 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin,
}
+ PyGILState_Release(gstate);
+
}
@@ -998,17 +1132,13 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin,
G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *plugin, PluginAction action, GType type)
{
gpointer result; /* Instance à retourner */
- PyThreadState *tstate; /* Contexte d'environnement */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyTypeObject *pytype; /* Classe Python concernée */
PyObject *instance; /* Initialisation forcée */
result = NULL;
- if (!_standalone)
- {
- tstate = get_pychrysalide_main_tstate();
- PyEval_RestoreThread(tstate);
- }
+ gstate = PyGILState_Ensure();
pytype = pygobject_lookup_class(type);
@@ -1021,31 +1151,7 @@ G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *pl
}
- if (!_standalone)
- PyEval_SaveThread();
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Fournit les informations du thread principal. *
-* *
-* Retour : Indications utiles à Python. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-PyThreadState *get_pychrysalide_main_tstate(void)
-{
- PyThreadState *result; /* Indications à retourner */
-
- result = _main_tstate;
+ PyGILState_Release(gstate);
return result;
@@ -1074,6 +1180,8 @@ void log_pychrysalide_exception(const char *prefix, ...)
PyObject *err_string; /* Description Python d'erreur */
const char *err_msg; /* Représentation humaine */
+ assert(PyGILState_Check() == 1);
+
if (PyErr_Occurred())
{
/* Base de la communication */
@@ -1120,7 +1228,7 @@ void log_pychrysalide_exception(const char *prefix, ...)
*
* C'est par exemple le cas quand un greffon Python ne peut se lancer
* correctement ; l'exception est alors levée à partir de la fonction
- * g_python_plugin_new() et le plantage intervient en sortie d'exécution,
+ * create_python_plugin() et le plantage intervient en sortie d'exécution,
* au moment de la libération de l'extension Python :
*
* ==14939== Jump to the invalid address stated on the next line
diff --git a/plugins/pychrysalide/core.h b/plugins/pychrysalide/core.h
index 6a7b9d1..88c4140 100644
--- a/plugins/pychrysalide/core.h
+++ b/plugins/pychrysalide/core.h
@@ -55,9 +55,6 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *, Plugin
/* Crée une instance à partir d'un type dynamique externe. */
G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *, PluginAction, GType);
-/* Fournit les informations du thread principal. */
-PyThreadState *get_pychrysalide_main_tstate(void);
-
/* Présente dans le journal une exception survenue. */
void log_pychrysalide_exception(const char *, ...);
diff --git a/plugins/pychrysalide/core/Makefile.am b/plugins/pychrysalide/core/Makefile.am
index 6c032c3..880823d 100644
--- a/plugins/pychrysalide/core/Makefile.am
+++ b/plugins/pychrysalide/core/Makefile.am
@@ -1,25 +1,20 @@
noinst_LTLIBRARIES = libpychrysacore.la
-libpychrysacore_la_SOURCES = \
- constants.h constants.c \
- demanglers.h demanglers.c \
- global.h global.c \
- logs.h logs.c \
- module.h module.c \
- params.h params.c \
- processors.h processors.c \
+libpychrysacore_la_SOURCES = \
+ constants.h constants.c \
+ demanglers.h demanglers.c \
+ global.h global.c \
+ logs.h logs.c \
+ module.h module.c \
+ params.h params.c \
+ processors.h processors.c \
queue.h queue.c
-libpychrysacore_la_LDFLAGS =
+libpychrysacore_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysacore_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/core/global.c b/plugins/pychrysalide/core/global.c
index ecaf2c6..9632e75 100644
--- a/plugins/pychrysalide/core/global.c
+++ b/plugins/pychrysalide/core/global.c
@@ -187,6 +187,52 @@ static PyObject *py_global_get_content_resolver(PyObject *self, PyObject *args)
* Paramètres : self = objet Python concerné par l'appel. *
* args = non utilisé ici. *
* *
+* Description : Fournit l'adresse de l'espace de noms principal pour ROST. *
+* *
+* Retour : Espace de noms racine de ROST ou NULL si aucun (!). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_global_get_rost_root_namespace(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GScanNamespace *root_ns; /* Espace de noms ROST racine */
+
+#define GLOBAL_GET_ROST_ROOT_NAMESPACE_METHOD PYTHON_METHOD_DEF \
+( \
+ get_rost_root_namespace, "", \
+ METH_NOARGS, py_global, \
+ "Get the root namespace for ROST." \
+ "\n" \
+ "The returned object is a pychrysalide.analysis.scan.ScanNamespace" \
+ " instance used as singleton; it should not be *None*." \
+)
+
+ root_ns = get_rost_root_namespace();
+
+ if (root_ns != NULL)
+ {
+ result = pygobject_new(G_OBJECT(root_ns));
+ g_object_unref(G_OBJECT(root_ns));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = non utilisé ici. *
+* *
* Description : Fournit l'adresse du projet courant. *
* *
* Retour : Adresse du résolveur global ou None si aucun. *
@@ -289,6 +335,7 @@ bool populate_core_module_with_global(void)
GLOBAL_IS_BATCH_MODE_METHOD,
GLOBAL_GET_CONTENT_EXPLORER_METHOD,
GLOBAL_GET_CONTENT_RESOLVER_METHOD,
+ GLOBAL_GET_ROST_ROOT_NAMESPACE_METHOD,
GLOBAL_GET_CURRENT_PROJECT_METHOD,
GLOBAL_SET_CURRENT_PROJECT_METHOD,
{ NULL }
diff --git a/plugins/pychrysalide/core/queue.c b/plugins/pychrysalide/core/queue.c
index d0fbed8..febf1b0 100644
--- a/plugins/pychrysalide/core/queue.c
+++ b/plugins/pychrysalide/core/queue.c
@@ -63,7 +63,6 @@ static PyObject *py_queue_wait_for_all_global_works(PyObject *, PyObject *);
static PyObject *py_queue_setup_global_work_group(PyObject *self, PyObject *args)
{
PyObject *result; /* Valeur à retourner */
- PyThreadState *_save; /* Sauvegarde de contexte */
wgroup_id_t wid; /* Identifiant de groupe */
#define QUEUE_SETUP_GLOBAL_WORK_GROUP_METHOD PYTHON_METHOD_DEF \
@@ -79,14 +78,10 @@ static PyObject *py_queue_setup_global_work_group(PyObject *self, PyObject *args
" unique identifier of a work group." \
)
- Py_UNBLOCK_THREADS;
-
wid = setup_global_work_group();
result = PyLong_FromUnsignedLongLong(wid);
- Py_BLOCK_THREADS;
-
return result;
}
@@ -109,8 +104,6 @@ static PyObject *py_queue_setup_tiny_global_work_group(PyObject *self, PyObject
{
PyObject *result; /* Valeur à retourner */
unsigned int count; /* Nombre de thread parallèle */
- PyThreadState *_save; /* Sauvegarde de contexte */
-
int ret; /* Bilan de lecture des args. */
wgroup_id_t wid; /* Identifiant de groupe */
@@ -131,8 +124,6 @@ static PyObject *py_queue_setup_tiny_global_work_group(PyObject *self, PyObject
count = 1;
- Py_UNBLOCK_THREADS;
-
ret = PyArg_ParseTuple(args, "|I", &count);
if (!ret) goto exit;
@@ -148,8 +139,6 @@ static PyObject *py_queue_setup_tiny_global_work_group(PyObject *self, PyObject
exit:
- Py_BLOCK_THREADS;
-
return result;
}
@@ -170,8 +159,6 @@ static PyObject *py_queue_setup_tiny_global_work_group(PyObject *self, PyObject
static PyObject *py_queue_wait_for_all_global_works(PyObject *self, PyObject *args)
{
- PyThreadState *_save; /* Sauvegarde de contexte */
-
#define QUEUE_WAIT_FOR_ALL_GLOBAL_WORKS_METHOD PYTHON_METHOD_DEF \
( \
wait_for_all_global_works, "", \
@@ -179,12 +166,8 @@ static PyObject *py_queue_wait_for_all_global_works(PyObject *self, PyObject *ar
"Wait for all global tasks being processed." \
)
- Py_UNBLOCK_THREADS;
-
wait_for_all_global_works();
- Py_BLOCK_THREADS;
-
Py_RETURN_NONE;
}
diff --git a/plugins/pychrysalide/debug/Makefile.am b/plugins/pychrysalide/debug/Makefile.am
index 4bd8e78..c653a6d 100644
--- a/plugins/pychrysalide/debug/Makefile.am
+++ b/plugins/pychrysalide/debug/Makefile.am
@@ -1,23 +1,14 @@
noinst_LTLIBRARIES = libpychrysadebug.la
-libpychrysadebug_la_SOURCES = \
- debugger.h debugger.c \
+libpychrysadebug_la_SOURCES = \
+ debugger.h debugger.c \
module.h module.c
-libpychrysadebug_la_LIBADD =
-
-libpychrysadebug_la_LDFLAGS =
+libpychrysadebug_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysadebug_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/debug/debugger.c b/plugins/pychrysalide/debug/debugger.c
index e65e295..b21087d 100644
--- a/plugins/pychrysalide/debug/debugger.c
+++ b/plugins/pychrysalide/debug/debugger.c
@@ -1195,7 +1195,7 @@ bool ensure_python_binary_debugger_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BINARY_DEBUGGER, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BINARY_DEBUGGER, type))
return false;
}
diff --git a/plugins/pychrysalide/format/Makefile.am b/plugins/pychrysalide/format/Makefile.am
index 68eb3be..337265d 100644
--- a/plugins/pychrysalide/format/Makefile.am
+++ b/plugins/pychrysalide/format/Makefile.am
@@ -1,30 +1,22 @@
noinst_LTLIBRARIES = libpychrysaformat.la
-libpychrysaformat_la_SOURCES = \
- constants.h constants.c \
- executable.h executable.c \
- flat.h flat.c \
- format.h format.c \
- known.h known.c \
- module.h module.c \
- strsym.h strsym.c \
- symbol.h symbol.c \
+libpychrysaformat_la_SOURCES = \
+ constants.h constants.c \
+ executable.h executable.c \
+ flat.h flat.c \
+ format.h format.c \
+ known.h known.c \
+ module.h module.c \
+ preload.h preload.c \
+ strsym.h strsym.c \
+ symbol.h symbol.c \
symiter.h symiter.c
-libpychrysaformat_la_LIBADD =
-
-libpychrysaformat_la_LDFLAGS =
+libpychrysaformat_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaformat_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/format/executable.c b/plugins/pychrysalide/format/executable.c
index ac0125d..ff2d14a 100644
--- a/plugins/pychrysalide/format/executable.c
+++ b/plugins/pychrysalide/format/executable.c
@@ -268,7 +268,7 @@ bool ensure_python_executable_format_is_registered(void)
if (!ensure_python_binary_format_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_EXE_FORMAT, type, get_python_binary_format_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_EXE_FORMAT, type))
return false;
}
diff --git a/plugins/pychrysalide/format/flat.c b/plugins/pychrysalide/format/flat.c
index 2c8e9fd..4df3646 100644
--- a/plugins/pychrysalide/format/flat.c
+++ b/plugins/pychrysalide/format/flat.c
@@ -173,7 +173,7 @@ bool ensure_python_flat_format_is_registered(void)
if (!ensure_python_executable_format_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_FLAT_FORMAT, type, get_python_executable_format_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_FLAT_FORMAT, type))
return false;
}
diff --git a/plugins/pychrysalide/format/format.c b/plugins/pychrysalide/format/format.c
index 66d346c..82c6c33 100644
--- a/plugins/pychrysalide/format/format.c
+++ b/plugins/pychrysalide/format/format.c
@@ -166,7 +166,7 @@ static PyObject *py_binary_format_new(PyTypeObject *type, PyObject *args, PyObje
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -1150,7 +1150,7 @@ bool ensure_python_binary_format_is_registered(void)
if (!ensure_python_known_format_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_BIN_FORMAT, type, get_python_known_format_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_BIN_FORMAT, type))
return false;
if (!define_binary_format_constants(type))
diff --git a/plugins/pychrysalide/format/known.c b/plugins/pychrysalide/format/known.c
index a2fc18c..3167ba2 100644
--- a/plugins/pychrysalide/format/known.c
+++ b/plugins/pychrysalide/format/known.c
@@ -132,7 +132,7 @@ static PyObject *py_known_format_new(PyTypeObject *type, PyObject *args, PyObjec
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -789,7 +789,7 @@ bool ensure_python_known_format_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_FORMAT, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_FORMAT, type))
return false;
}
diff --git a/plugins/pychrysalide/format/module.c b/plugins/pychrysalide/format/module.c
index 52dc58b..62c15ed 100644
--- a/plugins/pychrysalide/format/module.c
+++ b/plugins/pychrysalide/format/module.c
@@ -32,6 +32,7 @@
#include "flat.h"
#include "format.h"
#include "known.h"
+#include "preload.h"
#include "strsym.h"
#include "symbol.h"
#include "symiter.h"
@@ -105,6 +106,7 @@ bool populate_format_module(void)
if (result) result = ensure_python_flat_format_is_registered();
if (result) result = ensure_python_known_format_is_registered();
if (result) result = ensure_python_binary_format_is_registered();
+ if (result) result = ensure_python_preload_info_is_registered();
if (result) result = ensure_python_string_symbol_is_registered();
if (result) result = ensure_python_binary_symbol_is_registered();
if (result) result = ensure_python_sym_iterator_is_registered();
diff --git a/plugins/pychrysalide/format/preload.c b/plugins/pychrysalide/format/preload.c
new file mode 100644
index 0000000..e4f2a9c
--- /dev/null
+++ b/plugins/pychrysalide/format/preload.c
@@ -0,0 +1,207 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * preload.c - équivalent Python du fichier "format/preload.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "preload.h"
+
+
+#include <pygobject.h>
+
+
+#include <format/preload-int.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(preload_info, G_TYPE_PRELOAD_INFO);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_preload_info_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_preload_info_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan d'initialisation */
+
+#define PRELOAD_INFO_DOC \
+ "The PreloadInfo object stores all kinds of disassembling" \
+ " information available from the analysis of a file format" \
+ " itsself.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " PreloadInfo()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_preload_info_type(void)
+{
+ static PyMethodDef py_preload_info_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_preload_info_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_preload_info_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.format.PreloadInfo",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = PRELOAD_INFO_DOC,
+
+ .tp_methods = py_preload_info_methods,
+ .tp_getset = py_preload_info_getseters,
+
+ .tp_init = py_preload_info_init,
+ .tp_new = py_preload_info_new,
+
+ };
+
+ return &py_preload_info_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.format.PreloadInfo'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_preload_info_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ArchContext' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_preload_info_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.format");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PRELOAD_INFO, 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 espace de préchargement. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_preload_info(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_preload_info_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 disassembly context");
+ break;
+
+ case 1:
+ *((GPreloadInfo **)dst) = G_PRELOAD_INFO(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/format/preload.h b/plugins/pychrysalide/format/preload.h
new file mode 100644
index 0000000..bf33e82
--- /dev/null
+++ b/plugins/pychrysalide/format/preload.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * preload.h - prototypes pour l'équivalent Python du fichier "format/preload.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_FORMAT_PRELOAD_H
+#define _PLUGINS_PYCHRYSALIDE_FORMAT_PRELOAD_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_preload_info_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.PreloadInfo'. */
+bool ensure_python_preload_info_is_registered(void);
+
+/* Tente de convertir en espace de préchargement. */
+int convert_to_preload_info(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_FORMAT_PRELOAD_H */
diff --git a/plugins/pychrysalide/format/strsym.c b/plugins/pychrysalide/format/strsym.c
index c85d61f..adc0e48 100644
--- a/plugins/pychrysalide/format/strsym.c
+++ b/plugins/pychrysalide/format/strsym.c
@@ -119,7 +119,7 @@ static PyObject *py_string_symbol_new(PyTypeObject *type, PyObject *args, PyObje
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -501,7 +501,7 @@ bool ensure_python_string_symbol_is_registered(void)
if (!ensure_python_binary_symbol_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_STR_SYMBOL, type, get_python_binary_symbol_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_STR_SYMBOL, type))
return false;
if (!define_string_symbol_constants(type))
diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c
index d6d6402..d3a9c1e 100644
--- a/plugins/pychrysalide/format/symbol.c
+++ b/plugins/pychrysalide/format/symbol.c
@@ -43,6 +43,7 @@
#include "../helpers.h"
#include "../analysis/routine.h"
#include "../analysis/db/items/comment.h"
+#include "../analysis/storage/serialize.h"
#include "../arch/instruction.h"
#include "../arch/vmpa.h"
#include "../glibext/linegen.h"
@@ -156,7 +157,7 @@ static PyObject *py_binary_symbol_new(PyTypeObject *type, PyObject *args, PyObje
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -214,6 +215,7 @@ static void py_binary_symbol_init_gclass(GBinSymbolClass *class, gpointer unused
static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol)
{
char *result; /* Etiquette à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
@@ -228,6 +230,8 @@ static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol)
result = NULL;
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(symbol));
if (has_python_method(pyobj, "_get_label"))
@@ -246,6 +250,8 @@ static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol)
Py_DECREF(pyobj);
+ PyGILState_Release(gstate);
+
return result;
}
@@ -973,7 +979,10 @@ bool ensure_python_binary_symbol_is_registered(void)
if (!ensure_python_line_generator_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_BIN_SYMBOL, type, &PyGObject_Type))
+ if (!ensure_python_serializable_object_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_BIN_SYMBOL, type))
return false;
if (!define_binary_symbol_constants(type))
diff --git a/plugins/pychrysalide/glibext/Makefile.am b/plugins/pychrysalide/glibext/Makefile.am
index cfed869..2ed2aa5 100644
--- a/plugins/pychrysalide/glibext/Makefile.am
+++ b/plugins/pychrysalide/glibext/Makefile.am
@@ -1,30 +1,32 @@
noinst_LTLIBRARIES = libpychrysaglibext.la
-libpychrysaglibext_la_SOURCES = \
- constants.h constants.c \
- binarycursor.h binarycursor.c \
- binportion.h binportion.c \
- buffercache.h buffercache.c \
- bufferline.h bufferline.c \
- bufferview.h bufferview.c \
- configuration.h configuration.c \
- linecursor.h linecursor.c \
- linegen.h linegen.c \
- loadedpanel.h loadedpanel.c \
- module.h module.c \
- named.h named.c \
+libpychrysaglibext_la_SOURCES = \
+ constants.h constants.c \
+ binarycursor.h binarycursor.c \
+ binportion.h binportion.c \
+ buffercache.h buffercache.c \
+ bufferline.h bufferline.c \
+ comparison.h comparison.c \
+ configuration.h configuration.c \
+ linecursor.h linecursor.c \
+ linegen.h linegen.c \
+ module.h module.c \
singleton.h singleton.c
-libpychrysaglibext_la_LDFLAGS =
+if BUILD_GTK_SUPPORT
+libpychrysaglibext_la_SOURCES += \
+ bufferview.h bufferview.c \
+ loadedpanel.h loadedpanel.c \
+ named.h named.c
-devdir = $(includedir)/chrysalide/$(subdir)
+endif
-dev_HEADERS = $(libpychrysaglibext_la_SOURCES:%c=)
+libpychrysaglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
+devdir = $(includedir)/chrysalide/$(subdir)
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+dev_HEADERS = $(libpychrysaglibext_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/glibext/binarycursor.c b/plugins/pychrysalide/glibext/binarycursor.c
index 4da040a..91dce3e 100644
--- a/plugins/pychrysalide/glibext/binarycursor.c
+++ b/plugins/pychrysalide/glibext/binarycursor.c
@@ -321,7 +321,7 @@ bool ensure_python_binary_cursor_is_registered(void)
if (!ensure_python_line_cursor_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_BINARY_CURSOR, type, get_python_line_cursor_type()))
+ if (!register_class_for_pygobject(dict, G_TYPE_BINARY_CURSOR, type))
return false;
}
diff --git a/plugins/pychrysalide/glibext/binportion.c b/plugins/pychrysalide/glibext/binportion.c
index 060f001..70eb314 100644
--- a/plugins/pychrysalide/glibext/binportion.c
+++ b/plugins/pychrysalide/glibext/binportion.c
@@ -112,7 +112,7 @@ static PyObject *py_bin_portion_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -674,7 +674,7 @@ bool ensure_python_binary_portion_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BIN_PORTION, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BIN_PORTION, type))
return false;
if (!define_binary_portion_constants(type))
diff --git a/plugins/pychrysalide/glibext/buffercache.c b/plugins/pychrysalide/glibext/buffercache.c
index 0cf3342..03301d6 100644
--- a/plugins/pychrysalide/glibext/buffercache.c
+++ b/plugins/pychrysalide/glibext/buffercache.c
@@ -88,9 +88,13 @@ static PyObject *py_buffer_cache_get_line_flags(PyObject *, PyObject *);
/* Retire une propriété particulière attachée à une ligne. */
static PyObject *py_buffer_cache_remove_line_flag(PyObject *, PyObject *);
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Retrouve une ligne au sein d'un tampon avec un indice. */
static PyObject *py_buffer_cache_find_line_by_index(PyObject *, PyObject *);
+#endif
+
/* Avance autant que possible vers une ligne idéale. */
static PyObject *py_buffer_cache_look_for_flag(PyObject *, PyObject *);
@@ -153,7 +157,7 @@ static PyObject *py_buffer_cache_new(PyTypeObject *type, PyObject *args, PyObjec
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -825,6 +829,9 @@ static PyObject *py_buffer_cache_remove_line_flag(PyObject *self, PyObject *args
}
+#ifdef INCLUDE_GTK_SUPPORT
+
+
/******************************************************************************
* *
* Paramètres : self = classe représentant un tampon de code. *
@@ -883,6 +890,9 @@ static PyObject *py_buffer_cache_find_line_by_index(PyObject *self, PyObject *ar
}
+#endif
+
+
/******************************************************************************
* *
* Paramètres : self = classe représentant un tampon de code. *
@@ -1157,7 +1167,9 @@ PyTypeObject *get_python_buffer_cache_type(void)
BUFFER_CACHE_ADD_LINE_FLAG_METHOD,
BUFFER_CACHE_GET_LINE_FLAGS_METHOD,
BUFFER_CACHE_REMOVE_LINE_FLAG_METHOD,
+#ifdef INCLUDE_GTK_SUPPORT
BUFFER_CACHE_FIND_LINE_BY_INDEX_METHOD,
+#endif
BUFFER_CACHE_LOOK_FOR_FLAG_METHOD,
{ NULL }
};
@@ -1221,7 +1233,7 @@ bool ensure_python_buffer_cache_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_CACHE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_CACHE, type))
return false;
}
diff --git a/plugins/pychrysalide/glibext/bufferline.c b/plugins/pychrysalide/glibext/bufferline.c
index c88fe7f..09404bc 100644
--- a/plugins/pychrysalide/glibext/bufferline.c
+++ b/plugins/pychrysalide/glibext/bufferline.c
@@ -106,7 +106,7 @@ static PyObject *py_buffer_line_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -339,7 +339,7 @@ bool ensure_python_buffer_line_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_LINE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_LINE, type))
return false;
if (!define_line_segment_constants(type))
diff --git a/plugins/pychrysalide/glibext/bufferview.c b/plugins/pychrysalide/glibext/bufferview.c
index 98cc10a..d4cbdc2 100644
--- a/plugins/pychrysalide/glibext/bufferview.c
+++ b/plugins/pychrysalide/glibext/bufferview.c
@@ -146,7 +146,7 @@ bool ensure_python_buffer_view_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_VIEW, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_VIEW, type))
return false;
}
diff --git a/plugins/pychrysalide/glibext/comparison.c b/plugins/pychrysalide/glibext/comparison.c
new file mode 100644
index 0000000..548f700
--- /dev/null
+++ b/plugins/pychrysalide/glibext/comparison.c
@@ -0,0 +1,341 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparison.c - équivalent Python du fichier "glibext/comparison.h"
+ *
+ * Copyright (C) 2018-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 "comparison.h"
+
+
+#include <pygobject.h>
+
+
+#include <glibext/comparison-int.h>
+
+
+#include "constants.h"
+#include "../access.h"
+#include "../helpers.h"
+#include "../analysis/content.h"
+
+
+
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void py_comparable_item_interface_init(GComparableItemIface *, gpointer *);
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool py_comparable_item_compare_rich(const GComparableItem *, const GComparableItem *, RichCmpOperation, bool *);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
+/* Effectue une comparaison avec un objet 'ComparableItem'. */
+static PyObject *py_comparable_item_richcompare(PyObject *, PyObject *, int);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* unused = adresse non utilisée ici. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_comparable_item_interface_init(GComparableItemIface *iface, gpointer *unused)
+{
+
+#define COMPARABLE_ITEM_DOC \
+ "ComparableItem provides an interface to compare objects.\n" \
+ "\n" \
+ "A typical class declaration for a new implementation looks like:\n" \
+ "\n" \
+ " class NewImplem(GObject.Object, ComparableItem):\n" \
+ " ...\n" \
+ "\n"
+
+ iface->cmp_rich = py_comparable_item_compare_rich;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à cnsulter pour une comparaison. *
+* other = second objet à cnsulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_comparable_item_compare_rich(const GComparableItem *item, const GComparableItem *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyitem; /* Objet Python concerné #1 */
+ PyObject *pyother; /* Objet Python concerné #2 */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyitem = pygobject_new(G_OBJECT(item));
+ pyother = pygobject_new(G_OBJECT(other));
+
+ pyret = PyObject_RichCompare(pyitem, pyother, op);
+
+ if (pyret != NULL)
+ {
+ ret = PyBool_Check(pyret);
+
+ if (ret)
+ {
+ *status = (pyret == Py_True);
+ result = true;
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(pyother);
+ Py_DECREF(pyitem);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier object Python à consulter. *
+* b = second object Python à consulter. *
+* op = type de comparaison menée. *
+* *
+* Description : Effectue une comparaison avec un objet 'ComparableItem'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_comparable_item_richcompare(PyObject *a, PyObject *b, int op)
+{
+ PyObject *result; /* Bilan à retourner */
+ int ret; /* Bilan de lecture des args. */
+ GComparableItem *item_a; /* Instance à manipuler #1 */
+ GComparableItem *item_b; /* Instance à manipuler #2 */
+ bool valid; /* Indication de validité */
+ bool status; /* Résultat d'une comparaison */
+
+ ret = PyObject_IsInstance(b, (PyObject *)get_python_comparable_item_type());
+ if (!ret)
+ {
+ result = Py_NotImplemented;
+ goto cmp_done;
+ }
+
+ item_a = G_COMPARABLE_ITEM(pygobject_get(a));
+ item_b = G_COMPARABLE_ITEM(pygobject_get(b));
+
+ valid = g_comparable_item_compare_rich(item_a, item_b, op, &status);
+
+ if (valid)
+ result = status ? Py_True : Py_False;
+ else
+ result = Py_NotImplemented;
+
+ cmp_done:
+
+ 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_comparable_item_type(void)
+{
+ static PyMethodDef py_comparable_item_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_comparable_item_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_comparable_item_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.glibext.ComparableItem",
+ .tp_basicsize = sizeof(PyObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = COMPARABLE_ITEM_DOC,
+
+ .tp_richcompare = py_comparable_item_richcompare,
+
+ .tp_methods = py_comparable_item_methods,
+ .tp_getset = py_comparable_item_getseters,
+
+ };
+
+ return &py_comparable_item_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....ComparableItem'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_comparable_item_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ComparableItem' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ static GInterfaceInfo info = { /* Paramètres d'inscription */
+
+ .interface_init = (GInterfaceInitFunc)py_comparable_item_interface_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+
+ };
+
+ type = get_python_comparable_item_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.glibext");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_interface_for_pygobject(dict, G_TYPE_COMPARABLE_ITEM, type, &info))
+ return false;
+
+ if (!define_comparable_item_constants(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 élément comparable. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_comparable_item(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_comparable_item_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 comparable item");
+ break;
+
+ case 1:
+ *((GComparableItem **)dst) = G_COMPARABLE_ITEM(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/glibext/comparison.h b/plugins/pychrysalide/glibext/comparison.h
new file mode 100644
index 0000000..79f7092
--- /dev/null
+++ b/plugins/pychrysalide/glibext/comparison.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparison.h - prototypes pour l'équivalent Python du fichier "glibext/comparison.h"
+ *
+ * Copyright (C) 2018 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_PYCHRYSALIDE_GLIBEXT_COMPARISON_H
+#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_COMPARISON_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_comparable_item_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.glibext.ComparableItem'. */
+bool ensure_python_comparable_item_is_registered(void);
+
+/* Tente de convertir en élément comparable. */
+int convert_to_comparable_item(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_COMPARISON_H */
diff --git a/plugins/pychrysalide/glibext/configuration.c b/plugins/pychrysalide/glibext/configuration.c
index b0586af..c630331 100644
--- a/plugins/pychrysalide/glibext/configuration.c
+++ b/plugins/pychrysalide/glibext/configuration.c
@@ -174,7 +174,7 @@ static PyObject *py_config_param_new(PyTypeObject *type, PyObject *args, PyObjec
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -733,7 +733,7 @@ bool ensure_python_config_param_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_CFG_PARAM, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_CFG_PARAM, type))
return false;
if (!define_config_param_constants(type))
@@ -1036,7 +1036,7 @@ static PyObject *py_generic_config_new(PyTypeObject *type, PyObject *args, PyObj
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -1580,7 +1580,7 @@ bool ensure_python_generic_config_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_GEN_CONFIG, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_GEN_CONFIG, type))
return false;
}
diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c
index 373d1bf..169ffa2 100644
--- a/plugins/pychrysalide/glibext/constants.c
+++ b/plugins/pychrysalide/glibext/constants.c
@@ -27,10 +27,13 @@
#include <i18n.h>
#include <glibext/bufferline.h>
+#include <glibext/comparison.h>
#include <glibext/configuration.h>
#include <glibext/linesegment.h>
#include <glibext/gbinportion.h>
-#include <glibext/gloadedpanel.h>
+#ifdef INCLUDE_GTK_SUPPORT
+# include <glibext/gloadedpanel.h>
+#endif
#include "../helpers.h"
@@ -250,6 +253,48 @@ int convert_to_buffer_line_flags(PyObject *arg, void *dst)
* *
* Paramètres : type = type dont le dictionnaire est à compléter. *
* *
+* Description : Définit les constantes relatives aux modes de comparaison. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_comparable_item_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "LT", RCO_LT);
+ if (result) result = add_const_to_group(values, "LE", RCO_LE);
+ if (result) result = add_const_to_group(values, "EQ", RCO_EQ);
+ if (result) result = add_const_to_group(values, "NE", RCO_NE);
+ if (result) result = add_const_to_group(values, "GT", RCO_GT);
+ if (result) result = add_const_to_group(values, "GE", RCO_GE);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, true, "RichCmpOperation", values,
+ "Modes for objects comparison.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
* Description : Définit les constantes relatives aux paramètres de config. *
* *
* Retour : true en cas de succès de l'opération, false sinon. *
@@ -471,6 +516,9 @@ int convert_to_rendering_tag_type(PyObject *arg, void *dst)
}
+#ifdef INCLUDE_GTK_SUPPORT
+
+
/******************************************************************************
* *
* Paramètres : type = type dont le dictionnaire est à compléter. *
@@ -566,3 +614,6 @@ int convert_to_scroll_position_tweak(PyObject *arg, void *dst)
return result;
}
+
+
+#endif
diff --git a/plugins/pychrysalide/glibext/constants.h b/plugins/pychrysalide/glibext/constants.h
index 342b7ad..4a4f6da 100644
--- a/plugins/pychrysalide/glibext/constants.h
+++ b/plugins/pychrysalide/glibext/constants.h
@@ -43,6 +43,9 @@ bool define_buffer_line_constants(PyTypeObject *);
/* Tente de convertir en constante BufferLineFlags. */
int convert_to_buffer_line_flags(PyObject *, void *);
+/* Définit les constantes relatives aux modes de comparaison. */
+bool define_comparable_item_constants(PyTypeObject *);
+
/* Définit les constantes relatives aux paramètres de configuration. */
bool define_config_param_constants(PyTypeObject *);
@@ -55,12 +58,16 @@ bool define_line_segment_constants(PyTypeObject *);
/* Tente de convertir en constante RenderingTagType. */
int convert_to_rendering_tag_type(PyObject *, void *);
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Définit les constantes relatives aux panneaux de chargement. */
bool define_loaded_panel_constants(PyTypeObject *);
/* Tente de convertir en constante ScrollPositionTweak. */
int convert_to_scroll_position_tweak(PyObject *, void *);
+#endif
+
#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_CONSTANTS_H */
diff --git a/plugins/pychrysalide/glibext/linecursor.c b/plugins/pychrysalide/glibext/linecursor.c
index 217234a..4ac7f85 100644
--- a/plugins/pychrysalide/glibext/linecursor.c
+++ b/plugins/pychrysalide/glibext/linecursor.c
@@ -184,7 +184,7 @@ bool ensure_python_line_cursor_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_LINE_CURSOR, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_LINE_CURSOR, type))
return false;
}
diff --git a/plugins/pychrysalide/glibext/module.c b/plugins/pychrysalide/glibext/module.c
index 634cf5c..3e4307a 100644
--- a/plugins/pychrysalide/glibext/module.c
+++ b/plugins/pychrysalide/glibext/module.c
@@ -33,6 +33,7 @@
#include "buffercache.h"
#include "bufferline.h"
#include "bufferview.h"
+#include "comparison.h"
#include "configuration.h"
#include "linecursor.h"
#include "linegen.h"
@@ -111,14 +112,19 @@ bool populate_glibext_module(void)
if (result) result = ensure_python_binary_portion_is_registered();
if (result) result = ensure_python_buffer_cache_is_registered();
if (result) result = ensure_python_buffer_line_is_registered();
+#ifdef INCLUDE_GTK_SUPPORT
if (result) result = ensure_python_buffer_view_is_registered();
+#endif
+ if (result) result = ensure_python_comparable_item_is_registered();
if (result) result = ensure_python_config_param_is_registered();
if (result) result = ensure_python_config_param_iterator_is_registered();
if (result) result = ensure_python_generic_config_is_registered();
if (result) result = ensure_python_line_cursor_is_registered();
if (result) result = ensure_python_line_generator_is_registered();
+#ifdef INCLUDE_GTK_SUPPORT
if (result) result = ensure_python_loaded_panel_is_registered();
if (result) result = ensure_python_named_widget_is_registered();
+#endif
if (result) result = ensure_python_singleton_factory_is_registered();
assert(result);
diff --git a/plugins/pychrysalide/glibext/singleton.c b/plugins/pychrysalide/glibext/singleton.c
index c4592ac..8491473 100644
--- a/plugins/pychrysalide/glibext/singleton.c
+++ b/plugins/pychrysalide/glibext/singleton.c
@@ -60,7 +60,7 @@ static gboolean py_singleton_candidate___eq__wrapper(const GSingletonCandidate *
static void py_singleton_candidate_set_ro_wrapper(GSingletonCandidate *);
/* Indique si le candidat est figé. */
-static bool py_singleton_candidate_is_ro_wrapper(GSingletonCandidate *);
+static bool py_singleton_candidate_is_ro_wrapper(const GSingletonCandidate *);
/* Fournit l'empreinte d'un candidat à une centralisation. */
static PyObject *py_singleton_candidate_hash(PyObject *, PyObject *);
@@ -499,7 +499,7 @@ static void py_singleton_candidate_set_ro_wrapper(GSingletonCandidate *candidate
* *
******************************************************************************/
-static bool py_singleton_candidate_is_ro_wrapper(GSingletonCandidate *candidate)
+static bool py_singleton_candidate_is_ro_wrapper(const GSingletonCandidate *candidate)
{
bool result; /* Etat à retourner */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
@@ -922,7 +922,7 @@ static PyObject *py_singleton_factory_new(PyTypeObject *type, PyObject *args, Py
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -1110,7 +1110,7 @@ bool ensure_python_singleton_factory_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_SINGLETON_FACTORY, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_SINGLETON_FACTORY, type))
return false;
}
diff --git a/plugins/pychrysalide/gtkext/Makefile.am b/plugins/pychrysalide/gtkext/Makefile.am
index 77cce65..2e1260f 100644
--- a/plugins/pychrysalide/gtkext/Makefile.am
+++ b/plugins/pychrysalide/gtkext/Makefile.am
@@ -1,19 +1,20 @@
noinst_LTLIBRARIES = libpychrysagtkext.la
-libpychrysagtkext_la_SOURCES = \
- blockdisplay.h blockdisplay.c \
- bufferdisplay.h bufferdisplay.c \
- displaypanel.h displaypanel.c \
- dockable.h dockable.c \
- easygtk.h easygtk.c \
- module.h module.c \
+libpychrysagtkext_la_SOURCES = \
+ blockdisplay.h blockdisplay.c \
+ bufferdisplay.h bufferdisplay.c \
+ displaypanel.h displaypanel.c \
+ dockable.h dockable.c \
+ easygtk.h easygtk.c \
+ module.h module.c \
named.h named.c
-libpychrysagtkext_la_LIBADD = \
+libpychrysagtkext_la_LIBADD = \
graph/libpychrysagtkextgraph.la
-libpychrysagtkext_la_LDFLAGS =
+libpychrysagtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -21,10 +22,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysagtkext_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-
SUBDIRS = graph
diff --git a/plugins/pychrysalide/gtkext/blockdisplay.c b/plugins/pychrysalide/gtkext/blockdisplay.c
index 6741553..b4b8515 100644
--- a/plugins/pychrysalide/gtkext/blockdisplay.c
+++ b/plugins/pychrysalide/gtkext/blockdisplay.c
@@ -115,7 +115,7 @@ bool ensure_python_block_display_is_registered(void)
if (!ensure_python_buffer_display_is_registered())
return false;
- if (!register_class_for_pygobject(dict, GTK_TYPE_BLOCK_DISPLAY, type, get_python_buffer_display_type()))
+ if (!register_class_for_pygobject(dict, GTK_TYPE_BLOCK_DISPLAY, type))
return false;
}
diff --git a/plugins/pychrysalide/gtkext/bufferdisplay.c b/plugins/pychrysalide/gtkext/bufferdisplay.c
index 310e60a..4babcc8 100644
--- a/plugins/pychrysalide/gtkext/bufferdisplay.c
+++ b/plugins/pychrysalide/gtkext/bufferdisplay.c
@@ -115,7 +115,7 @@ bool ensure_python_buffer_display_is_registered(void)
if (!ensure_python_display_panel_is_registered())
return false;
- if (!register_class_for_pygobject(dict, GTK_TYPE_BUFFER_DISPLAY, type, get_python_display_panel_type()))
+ if (!register_class_for_pygobject(dict, GTK_TYPE_BUFFER_DISPLAY, type))
return false;
}
diff --git a/plugins/pychrysalide/gtkext/displaypanel.c b/plugins/pychrysalide/gtkext/displaypanel.c
index dc7b8e5..a871af9 100644
--- a/plugins/pychrysalide/gtkext/displaypanel.c
+++ b/plugins/pychrysalide/gtkext/displaypanel.c
@@ -98,42 +98,23 @@ PyTypeObject *get_python_display_panel_type(void)
bool ensure_python_display_panel_is_registered(void)
{
- bool result; /* Bilan à retourner */
PyTypeObject *type; /* Type Python 'DisplayPanel' */
- PyObject *parent_mod; /* Module Python Fixed */
- PyObject *fixed; /* Module "GtkFixed" */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- result = false;
-
type = get_python_display_panel_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
module = get_access_to_python_module("pychrysalide.gtkext");
- parent_mod = PyImport_ImportModule("gi.repository.Gtk");
-
- if (parent_mod == NULL)
- goto rpdp_exit;
-
- fixed = PyObject_GetAttrString(parent_mod, "Fixed");
-
- Py_DECREF(parent_mod);
-
dict = PyModule_GetDict(module);
- result = register_class_for_pygobject(dict, GTK_TYPE_DISPLAY_PANEL, type, (PyTypeObject *)fixed);
- Py_DECREF(fixed);
+ if (!register_class_for_pygobject(dict, GTK_TYPE_DISPLAY_PANEL, type))
+ return false;
}
- else
- result = true;
-
- rpdp_exit:
-
- return result;
+ return true;
}
diff --git a/plugins/pychrysalide/gtkext/graph/Makefile.am b/plugins/pychrysalide/gtkext/graph/Makefile.am
index 7e9b5e5..25e3088 100644
--- a/plugins/pychrysalide/gtkext/graph/Makefile.am
+++ b/plugins/pychrysalide/gtkext/graph/Makefile.am
@@ -1,21 +1,16 @@
noinst_LTLIBRARIES = libpychrysagtkextgraph.la
-libpychrysagtkextgraph_la_SOURCES = \
- constants.h constants.c \
- cluster.h cluster.c \
- edge.h edge.c \
+libpychrysagtkextgraph_la_SOURCES = \
+ constants.h constants.c \
+ cluster.h cluster.c \
+ edge.h edge.c \
module.h module.c
-libpychrysagtkextgraph_la_LDFLAGS =
+libpychrysagtkextgraph_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysagtkextgraph_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/gtkext/graph/cluster.c b/plugins/pychrysalide/gtkext/graph/cluster.c
index fc73276..11cb8fa 100644
--- a/plugins/pychrysalide/gtkext/graph/cluster.c
+++ b/plugins/pychrysalide/gtkext/graph/cluster.c
@@ -656,7 +656,7 @@ bool ensure_python_graph_cluster_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_GRAPH_CLUSTER, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_GRAPH_CLUSTER, type))
return false;
}
diff --git a/plugins/pychrysalide/gtkext/graph/edge.c b/plugins/pychrysalide/gtkext/graph/edge.c
index ce20ce9..d016e30 100644
--- a/plugins/pychrysalide/gtkext/graph/edge.c
+++ b/plugins/pychrysalide/gtkext/graph/edge.c
@@ -267,7 +267,7 @@ bool ensure_python_graph_edge_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_GRAPH_EDGE, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_GRAPH_EDGE, type))
return false;
if (!define_graph_edge_constants(type))
diff --git a/plugins/pychrysalide/gtkext/named.c b/plugins/pychrysalide/gtkext/named.c
index e272097..ee963de 100644
--- a/plugins/pychrysalide/gtkext/named.c
+++ b/plugins/pychrysalide/gtkext/named.c
@@ -99,7 +99,7 @@ static PyObject *py_built_named_widget_new(PyTypeObject *type, PyObject *args, P
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -278,12 +278,7 @@ PyTypeObject *get_python_built_named_widget_type(void)
};
- static PyTypeObject *result = NULL;
-
- if (result == NULL)
- result = define_python_dynamic_type(&py_built_named_widget_type);
-
- return result;
+ return &py_built_named_widget_type;
}
@@ -317,7 +312,7 @@ bool ensure_python_built_named_widget_is_registered(void)
if (!ensure_python_named_widget_is_registered())
return false;
- if (!register_class_for_pygobject(dict, GTK_TYPE_BUILT_NAMED_WIDGET, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, GTK_TYPE_BUILT_NAMED_WIDGET, type))
return false;
}
diff --git a/plugins/pychrysalide/gui/Makefile.am b/plugins/pychrysalide/gui/Makefile.am
index 360f7ff..de2e888 100644
--- a/plugins/pychrysalide/gui/Makefile.am
+++ b/plugins/pychrysalide/gui/Makefile.am
@@ -1,18 +1,19 @@
noinst_LTLIBRARIES = libpychrysagui.la
-libpychrysagui_la_SOURCES = \
- constants.h constants.c \
- item.h item.c \
- menubar.h menubar.c \
- module.h module.c \
+libpychrysagui_la_SOURCES = \
+ constants.h constants.c \
+ item.h item.c \
+ menubar.h menubar.c \
+ module.h module.c \
panel.h panel.c
-libpychrysagui_la_LIBADD = \
- core/libpychrysaguicore.la \
+libpychrysagui_la_LIBADD = \
+ core/libpychrysaguicore.la \
panels/libpychrysaguipanels.la
-libpychrysagui_la_LDFLAGS =
+libpychrysagui_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
@@ -20,9 +21,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysagui_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = core panels
diff --git a/plugins/pychrysalide/gui/core/Makefile.am b/plugins/pychrysalide/gui/core/Makefile.am
index 02f3596..8f49176 100644
--- a/plugins/pychrysalide/gui/core/Makefile.am
+++ b/plugins/pychrysalide/gui/core/Makefile.am
@@ -1,21 +1,16 @@
noinst_LTLIBRARIES = libpychrysaguicore.la
-libpychrysaguicore_la_SOURCES = \
- global.h global.c \
- items.h items.c \
- module.h module.c \
+libpychrysaguicore_la_SOURCES = \
+ global.h global.c \
+ items.h items.c \
+ module.h module.c \
panels.h panels.c
-libpychrysaguicore_la_LDFLAGS =
+libpychrysaguicore_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaguicore_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/gui/item.c b/plugins/pychrysalide/gui/item.c
index 2046587..0c604b5 100644
--- a/plugins/pychrysalide/gui/item.c
+++ b/plugins/pychrysalide/gui/item.c
@@ -291,19 +291,16 @@ static GtkWidget *py_editor_item_get_widget_wrapper(const GEditorItem *item)
static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedContent *old, GLoadedContent *new)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyThreadState *tstate; /* Contexte d'environnement */
PyObject *pyold; /* Conversion ou None */
PyObject *pynew; /* Conversion ou None */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Retour de Python */
- pyobj = pygobject_new(G_OBJECT(item));
-
- tstate = get_pychrysalide_main_tstate();
+ gstate = PyGILState_Ensure();
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
+ pyobj = pygobject_new(G_OBJECT(item));
if (has_python_method(pyobj, "_change_content"))
{
@@ -334,8 +331,7 @@ static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedCont
}
- if (tstate != NULL)
- PyEval_SaveThread();
+ PyGILState_Release(gstate);
}
@@ -356,19 +352,16 @@ static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedCont
static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel *old, GLoadedPanel *new)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyThreadState *tstate; /* Contexte d'environnement */
PyObject *pyold; /* Conversion ou None */
PyObject *pynew; /* Conversion ou None */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Retour de Python */
- pyobj = pygobject_new(G_OBJECT(item));
-
- tstate = get_pychrysalide_main_tstate();
+ gstate = PyGILState_Ensure();
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
+ pyobj = pygobject_new(G_OBJECT(item));
if (has_python_method(pyobj, "_change_view"))
{
@@ -399,8 +392,7 @@ static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel *
}
- if (tstate != NULL)
- PyEval_SaveThread();
+ PyGILState_Release(gstate);
}
@@ -420,17 +412,14 @@ static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel *
static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel *panel)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyThreadState *tstate; /* Contexte d'environnement */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Retour de Python */
- pyobj = pygobject_new(G_OBJECT(item));
-
- tstate = get_pychrysalide_main_tstate();
+ gstate = PyGILState_Ensure();
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
+ pyobj = pygobject_new(G_OBJECT(item));
if (has_python_method(pyobj, "_update_view"))
{
@@ -444,8 +433,7 @@ static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel *
}
- if (tstate != NULL)
- PyEval_SaveThread();
+ PyGILState_Release(gstate);
}
@@ -466,17 +454,14 @@ static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel *
static void py_editor_item_track_cursor_wrapper(GEditorItem *item, GLoadedPanel *panel, const GLineCursor *cursor)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyThreadState *tstate; /* Contexte d'environnement */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Retour de Python */
- pyobj = pygobject_new(G_OBJECT(item));
-
- tstate = get_pychrysalide_main_tstate();
+ gstate = PyGILState_Ensure();
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
+ pyobj = pygobject_new(G_OBJECT(item));
if (has_python_method(pyobj, "_track_cursor"))
{
@@ -491,8 +476,7 @@ static void py_editor_item_track_cursor_wrapper(GEditorItem *item, GLoadedPanel
}
- if (tstate != NULL)
- PyEval_SaveThread();
+ PyGILState_Release(gstate);
}
@@ -513,17 +497,14 @@ static void py_editor_item_track_cursor_wrapper(GEditorItem *item, GLoadedPanel
static void py_editor_item_focus_cursor_wrapper(GEditorItem *item, GLoadedContent *content, const GLineCursor *cursor)
{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
- PyThreadState *tstate; /* Contexte d'environnement */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Retour de Python */
- pyobj = pygobject_new(G_OBJECT(item));
-
- tstate = get_pychrysalide_main_tstate();
+ gstate = PyGILState_Ensure();
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
+ pyobj = pygobject_new(G_OBJECT(item));
if (has_python_method(pyobj, "_focus_cursor"))
{
@@ -538,8 +519,7 @@ static void py_editor_item_focus_cursor_wrapper(GEditorItem *item, GLoadedConten
}
- if (tstate != NULL)
- PyEval_SaveThread();
+ PyGILState_Release(gstate);
}
@@ -711,7 +691,7 @@ bool ensure_python_editor_item_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_EDITOR_ITEM, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_EDITOR_ITEM, type))
return false;
}
diff --git a/plugins/pychrysalide/gui/menubar.c b/plugins/pychrysalide/gui/menubar.c
index 5c6270e..29b76ac 100644
--- a/plugins/pychrysalide/gui/menubar.c
+++ b/plugins/pychrysalide/gui/menubar.c
@@ -160,7 +160,10 @@ bool ensure_python_menu_bar_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_MENU_BAR, type, get_python_editor_item_type()))
+ if (!ensure_python_editor_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_MENU_BAR, type))
return false;
}
diff --git a/plugins/pychrysalide/gui/panel.c b/plugins/pychrysalide/gui/panel.c
index 2afb2a1..949243c 100644
--- a/plugins/pychrysalide/gui/panel.c
+++ b/plugins/pychrysalide/gui/panel.c
@@ -164,7 +164,7 @@ static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject
if (first_time)
{
- status = register_class_for_dynamic_pygobject(gtype, type, base);
+ status = register_class_for_dynamic_pygobject(gtype, type);
if (!status)
{
@@ -1188,8 +1188,7 @@ bool ensure_python_panel_item_is_registered(void)
if (!ensure_python_dockable_is_registered())
return false;
- if (!_register_class_for_pygobject(dict, G_TYPE_PANEL_ITEM, type,
- get_python_editor_item_type(), get_python_dockable_type(), NULL))
+ if (!register_class_for_pygobject(dict, G_TYPE_PANEL_ITEM, type))
return false;
if (!define_panel_item_constants(type))
diff --git a/plugins/pychrysalide/gui/panels/Makefile.am b/plugins/pychrysalide/gui/panels/Makefile.am
index 9585ec4..067c798 100644
--- a/plugins/pychrysalide/gui/panels/Makefile.am
+++ b/plugins/pychrysalide/gui/panels/Makefile.am
@@ -1,19 +1,14 @@
noinst_LTLIBRARIES = libpychrysaguipanels.la
-libpychrysaguipanels_la_SOURCES = \
- module.h module.c \
+libpychrysaguipanels_la_SOURCES = \
+ module.h module.c \
updating.h updating.c
-libpychrysaguipanels_la_LDFLAGS =
+libpychrysaguipanels_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaguipanels_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 92a5db9..c2b1868 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -32,11 +32,14 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <gtk/gtk.h>
+#ifdef INCLUDE_GTK_SUPPORT
+# include <gtk/gtk.h>
+#endif
#include <i18n.h>
#include <common/extstr.h>
+#include <plugins/dt.h>
#include "access.h"
@@ -233,6 +236,8 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args
PyObject *traceback; /* Pile d'appels de l'exception*/
PyObject *refmsg; /* Message de référence */
+ assert(PyGILState_Check() == 1);
+
/* Exécution */
result = NULL;
@@ -505,6 +510,131 @@ bool register_python_module_object(PyObject *module, PyTypeObject *type)
/******************************************************************************
* *
+* Paramètres : type = type du nouvel objet à mettre en place. *
+* gbase = type de base natif. *
+* args = éventuelle liste d'arguments. *
+* kwds = éventuel dictionnaire de valeurs mises à disposition.*
+* *
+* Description : Accompagne la création d'une instance dérivée en Python. *
+* *
+* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *python_constructor_with_dynamic_gtype(PyTypeObject *type, GType gbase, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Objet à retourner */
+ PyTypeObject *base; /* Type parent version Python */
+ bool first_time; /* Evite les multiples passages*/
+ GType gtype; /* Nouveau type de processeur */
+ bool status; /* Bilan d'un enregistrement */
+
+ /* Validations diverses */
+
+ base = pygobject_lookup_class(gbase);
+
+ if (type == base)
+ goto simple_way;
+
+ /* Mise en place d'un type dédié */
+
+ first_time = (g_type_from_name(type->tp_name) == 0);
+
+ gtype = build_dynamic_type(gbase, type->tp_name, NULL, NULL, NULL);
+
+ if (first_time)
+ {
+ status = register_class_for_dynamic_pygobject(gtype, type);
+
+ if (!status)
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ }
+
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ simple_way:
+
+ result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du nouvel objet à mettre en place. *
+* gbase = type de base natif. *
+* cinit = procédure d'initialisation de la classe associée. *
+* args = éventuelle liste d'arguments. *
+* kwds = éventuel dictionnaire de valeurs mises à disposition.*
+* *
+* Description : Accompagne la création d'une instance dérivée en Python. *
+* *
+* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *python_abstract_constructor_with_dynamic_gtype(PyTypeObject *type, GType gbase, GClassInitFunc cinit, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Objet à retourner */
+ PyTypeObject *base; /* Type parent version Python */
+ bool first_time; /* Evite les multiples passages*/
+ GType gtype; /* Nouveau type de processeur */
+ bool status; /* Bilan d'un enregistrement */
+
+ /* Validations diverses */
+
+ base = pygobject_lookup_class(gbase);
+
+ if (type == base)
+ {
+ result = NULL;
+ PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
+ goto exit;
+ }
+
+ /* Mise en place d'un type dédié */
+
+ first_time = (g_type_from_name(type->tp_name) == 0);
+
+ gtype = build_dynamic_type(gbase, type->tp_name, cinit, NULL, NULL);
+
+ if (first_time)
+ {
+ status = register_class_for_dynamic_pygobject(gtype, type);
+
+ if (!status)
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ }
+
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : type = type du nouvel objet à mettre en place. *
* args = éventuelle liste d'arguments. *
* kwds = éventuel dictionnaire de valeurs mises à disposition. *
@@ -659,7 +789,7 @@ PyObject *not_yet_implemented_getter(PyObject *self, void *closure)
/******************************************************************************
* *
-* Paramètres : spec = définition à mettre en place dynamiquement. *
+* Paramètres : otype = définition à mettre en place dynamiquement. *
* *
* Description : Définit dans le tas de Python un nouveau type. *
* *
@@ -669,102 +799,63 @@ PyObject *not_yet_implemented_getter(PyObject *self, void *closure)
* *
******************************************************************************/
-PyTypeObject *define_python_dynamic_type(const PyTypeObject *spec)
+PyTypeObject *define_python_dynamic_type(const PyTypeObject *otype)
{
PyTypeObject *result; /* Définition créée à renvoyer */
- PyTypeObject *type; /* Type de tous les types */
- size_t size; /* Taille de la définition */
- char *s; /* Marqueur de début de chaîne */
- PyHeapTypeObject *hobj; /* Version réelle du type créé */
+ PyType_Slot slots[10]; /* Emplacements pour infos */
+ PyType_Spec spec; /* Définition du type */
+ PyType_Slot *iter; /* Boucle de parcours */
+ PyObject *bases; /* Bases de construction */
- /**
- * Le cahier des charges est ici d'éviter les erreurs suivantes :
- *
- * TypeError: type 'XXX' is not dynamically allocated but its base type 'YYY' is dynamically allocated
- * Fatal Python error: unexpected exception during garbage collection
- *
- * L'allocation dynamique est marquée par le fanion Py_TPFLAGS_HEAPTYPE.
- *
- * Une des rares fonctions qui appliquent ce fanion est PyType_FromSpecWithBases(),
- * mais elle appelle ensuite PyType_Ready(), ce qui est incompatible avec des modifications
- * utltérieures avant un appel à pygobject_register_class().
- *
- * Le code suivant s'inspire fortement des méthodes originales de Python,
- * dont les mécanismes employés par PyType_GenericAlloc().
- */
-
- type = &PyType_Type;
- size = _PyObject_SIZE(type);
-
- if (PyType_IS_GC(type))
- result = (PyTypeObject *)_PyObject_GC_Malloc(size);
- else
- result = (PyTypeObject *)PyObject_MALLOC(size);
-
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
- Py_INCREF(type);
-
- /* Définitions sommaires */
-
- memset(result, 0, sizeof(PyHeapTypeObject));
+ bases = PyTuple_Pack(1, &PyType_Type);
- memcpy(result, spec, sizeof(PyTypeObject));
-
- result->tp_flags |= Py_TPFLAGS_HEAPTYPE;
-
- /* Définitions des noms */
-
- /**
- * Pour un type dynamique, les désignations ne s'appuient pas sur la partie réservée
- * au type, mais sur les données suivantes (cf. type_name() et type_qualname()).
- *
- * Les deux fonctions désignées sont par ailleurs facilement accessibles :
- *
- * #0 0x0000555555689bf0 in type_qualname (...) at Objects/typeobject.c:393
- * #1 0x000055555568b3b4 in type_repr (...) at Objects/typeobject.c:855
- * #2 0x0000555555693574 in object_str (...) at Objects/typeobject.c:3511
- * #3 0x0000555555670d02 in PyObject_Str (...) at Objects/object.c:535
- * ...
- *
- * On s'inspire donc du contenu de PyType_FromSpecWithBases() pour éviter tout
- * plantage du fait de données non initialisées.
- */
-
- hobj = (PyHeapTypeObject *)result;
-
- s = strrchr(spec->tp_name, '.');
-
- if (s == NULL)
- s = (char *)spec->tp_name;
- else
- s++;
+ spec.name = otype->tp_name;
+ spec.basicsize = otype->tp_basicsize;
+ spec.flags = otype->tp_flags;
+ spec.slots = slots;
- hobj->ht_name = PyUnicode_FromString(s);
- assert(hobj->ht_name != NULL);
+ iter = &slots[0];
- hobj->ht_qualname = hobj->ht_name;
- Py_INCREF(hobj->ht_qualname);
+ if (otype->tp_doc != NULL)
+ {
+ iter->slot = Py_tp_doc;
+ iter->pfunc = (void *)otype->tp_doc;
+ iter++;
+ }
- result->tp_as_async = &hobj->as_async;
- result->tp_as_number = &hobj->as_number;
- result->tp_as_sequence = &hobj->as_sequence;
- result->tp_as_mapping = &hobj->as_mapping;
- result->tp_as_buffer = &hobj->as_buffer;
+ if (otype->tp_methods != NULL)
+ {
+ iter->slot = Py_tp_methods;
+ iter->pfunc = otype->tp_methods;
+ iter++;
+ }
- hobj->ht_cached_keys = _PyDict_NewKeysForClass();
+ if (otype->tp_getset != NULL)
+ {
+ iter->slot = Py_tp_getset;
+ iter->pfunc = otype->tp_getset;
+ iter++;
+ }
+ if (otype->tp_init != NULL)
+ {
+ iter->slot = Py_tp_init;
+ iter->pfunc = otype->tp_init;
+ iter++;
+ }
+ if (otype->tp_new != NULL)
+ {
+ iter->slot = Py_tp_new;
+ iter->pfunc = otype->tp_new;
+ iter++;
+ }
+ iter->slot = 0;
-#if 0
- if (type->tp_itemsize == 0)
- (void)PyObject_INIT(result, type);
- else
- (void) PyObject_INIT_VAR((PyVarObject *)result, type, 0);
+ result = (PyTypeObject *)PyType_FromSpecWithBases(&spec, bases);
- if (PyType_IS_GC(type))
- _PyObject_GC_TRACK(result);
-#endif
+ Py_DECREF(bases);
return result;
@@ -800,7 +891,6 @@ static void define_auto_documentation(PyTypeObject *type)
* Paramètres : dict = dictionnaire où conserver une référence au type créé.*
* gtype = type dans sa version GLib. *
* type = type dans sa version Python. *
-* base = type de base de l'objet. *
* *
* Description : Enregistre correctement une surcouche de conversion GObject. *
* *
@@ -810,13 +900,11 @@ static void define_auto_documentation(PyTypeObject *type)
* *
******************************************************************************/
-bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type, PyTypeObject *base, ...)
+bool register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type)
{
bool result; /* Bilan à retourner */
- Py_ssize_t size; /* Taille de liste actuelle */
- PyObject *static_bases; /* Base(s) de l'objet */
- va_list ap; /* Parcours des arguments */
- PyTypeObject *static_base; /* Base à rajouter à la liste */
+ GType parent_type; /* Type parent version GObject */
+ PyTypeObject *base; /* Type parent version Python */
assert(gtype != G_TYPE_INVALID);
@@ -841,45 +929,17 @@ bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *ty
* Et quelqu'un doit se coller à la tâche. PyGObject ne fait rien, donc...
*/
+ parent_type = g_type_parent(gtype);
+
+ base = pygobject_lookup_class(parent_type);
+
if (type->tp_basicsize < base->tp_basicsize)
{
assert(type->tp_basicsize == 0);
type->tp_basicsize = base->tp_basicsize;
}
- size = 1;
- static_bases = PyTuple_New(size);
-
- Py_INCREF(base);
- PyTuple_SetItem(static_bases, 0, (PyObject *)base);
-
- va_start(ap, base);
-
- while (1)
- {
- static_base = va_arg(ap, PyTypeObject *);
-
- if (static_base == NULL) break;
-
- _PyTuple_Resize(&static_bases, ++size);
-
- Py_INCREF(static_base);
- PyTuple_SetItem(static_bases, size - 1, (PyObject *)static_base);
-
- }
-
- va_end(ap);
-
- /**
- * les renseignements suivants ne semblent pas nécessaires...
- */
-
- /*
- type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
- type->tp_dictoffset = offsetof(PyGObject, inst_dict);
- */
-
- pygobject_register_class(dict, NULL, gtype, type, static_bases);
+ pygobject_register_class(dict, NULL, gtype, type, NULL);
if (PyErr_Occurred() == NULL)
result = true;
@@ -956,10 +1016,8 @@ bool register_interface_for_pygobject(PyObject *dict, GType gtype, PyTypeObject
/******************************************************************************
* *
-* Paramètres : dict = dictionnaire où conserver une référence au type créé.*
-* gtype = type dans sa version GLib. *
+* Paramètres : gtype = type dans sa version GLib. *
* type = type dans sa version Python. *
-* base = type de base de l'objet. *
* *
* Description : Enregistre un type Python dérivant d'un type GLib dynamique. *
* *
@@ -969,7 +1027,7 @@ bool register_interface_for_pygobject(PyObject *dict, GType gtype, PyTypeObject
* *
******************************************************************************/
-bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTypeObject *base)
+bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type)
{
bool result; /* Bilan à retourner */
PyTypeObject *legacy_parent; /* Type parent d'origine */
@@ -1024,9 +1082,9 @@ bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTyp
dict = PyModule_GetDict(module);
- result = _register_class_for_pygobject(dict, gtype, type, &PyGObject_Type, base, NULL);
+ result = register_class_for_pygobject(dict, gtype, type);
- Py_TYPE(type) = legacy_parent;
+ Py_SET_TYPE(type, legacy_parent);
/**
* Comme la mise en place dynamique de nouveau GType court-circuite les
@@ -1189,6 +1247,9 @@ int convert_to_gobject(PyObject *arg, void *dst)
}
+#ifdef INCLUDE_GTK_SUPPORT
+
+
/******************************************************************************
* *
* Paramètres : arg = argument quelconque à tenter de convertir. *
@@ -1299,6 +1360,9 @@ int convert_to_gtk_container(PyObject *arg, void *dst)
}
+#endif
+
+
/******************************************************************************
* *
* Paramètres : color = couleur dans sa définition native à copier. *
@@ -1440,15 +1504,15 @@ int convert_to_gdk_rgba(PyObject *arg, void *dst)
* *
* Description : Officialise un groupe de constantes avec sémentique. *
* *
-* Retour : true en cas de succès de l'opération, false sinon. *
+* Retour : Groupe de constantes mis en place ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc)
+PyObject *_attach_constants_group(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc)
{
- bool result; /* Bilan à retourner */
+ PyObject *result; /* Instance à retourner */
PyObject *enum_mod; /* Module Python enum */
PyObject *class; /* Classe "Enum*" */
PyObject *str_obj; /* Conversion en Python */
@@ -1462,7 +1526,7 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons
PyObject *features; /* Module à recompléter */
PyObject *features_dict; /* Dictionnaire à compléter */
- result = false;
+ result = NULL;
/* Recherche de la classe Python */
@@ -1539,7 +1603,8 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons
ret = PyDict_SetItemString(features_dict, name, new);
if (ret != 0) goto register_1_error;
- result = true;
+ result = new;
+ Py_INCREF(result);
/* Sortie propre */
@@ -1570,6 +1635,99 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons
}
+/******************************************************************************
+* *
+* Paramètres : owner = désignation du propriétaire du dictionnaire visé. *
+* dict = dictionnaire dont le contenu est à compléter. *
+* flags = indique le type d'énumération ciblée. *
+* name = désignation humaine du groupe à constituer. *
+* values = noms et valeurs associées. *
+* doc = documentation à associer au groupe. *
+* gtype = énumération GLib à lier. *
+* *
+* Description : Officialise un groupe de constantes avec lien GLib. *
+* *
+* Retour : Groupe de constantes mis en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *_attach_constants_group_with_pyg_enum(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc, GType gtype)
+{
+ PyObject *result; /* Instance à retourner */
+ PyObject *values_set; /* Zone pour nouvelles valeurs */
+ int ret; /* Bilan d'une insertion */
+ PyObject *new; /* Nouvelle instance en place */
+ PyObject *values_src; /* Source de nouvelles valeurs */
+ PyObject *values_dest; /* Destination des valeurs */
+
+ static GQuark pygenum_class_key = 0; /* Clef d'accès au marquage */
+
+ result = NULL;
+
+ /**
+ * Le seul intérêt d'un tel enregistrement en bonne et due forme est de
+ * permettre une impression, via str() ou repr(), de l'énumération
+ * transcrite en GLib via g_enum_register_static() et potentiellement
+ * convertie de façon brusque par _pygi_argument_to_object(), lors d'une
+ * émission de signal par exemple.
+ *
+ * La satisfaction de la fonction pyg_enum_from_gtype() est ainsi recherchée.
+ * Tous les éléments sont normalement mis en place à partir de la fonction
+ * pyg_enum_add().
+ */
+
+ /* Préparation du réceptacle */
+
+ values_set = PyDict_New();
+
+ ret = PyDict_SetItemString(values, "__enum_values__", values_set);
+
+ Py_DECREF(values_set);
+
+ if (ret != 0) goto exit;
+
+ /* Création */
+
+ new = _attach_constants_group(owner, dict, flags, name, values, doc);
+ if (new == NULL) goto exit;
+
+ /* Actualisation des valeurs */
+
+ values_src = PyDict_GetItemString(((PyTypeObject *)new)->tp_dict, "_value2member_map_");
+ if (values_src == NULL) goto exit_without_src;
+
+ values_dest = PyDict_GetItemString(((PyTypeObject *)new)->tp_dict, "__enum_values__");
+ if (values_dest == NULL) goto exit_without_dest;
+
+ assert(values_dest == values_set);
+
+ ret = PyDict_Merge(values_dest, values_src, true);
+
+ if (ret == 0)
+ {
+ result = new;
+ Py_INCREF(result);
+
+ if (pygenum_class_key == 0)
+ pygenum_class_key = g_quark_from_static_string("PyGEnum::class");
+
+ g_type_set_qdata(gtype, pygenum_class_key, result);
+
+ }
+
+ exit_without_dest:
+ exit_without_src:
+
+ Py_DECREF(new);
+
+ exit:
+
+ return result;
+
+}
+
/******************************************************************************
* *
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index 931be95..57cf96d 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -29,7 +29,9 @@
#include <assert.h>
#include <glib-object.h>
#include <stdbool.h>
-#include <gdk/gdk.h>
+#ifdef INCLUDE_GTK_SUPPORT
+# include <gdk/gdk.h>
+#endif
@@ -85,26 +87,21 @@ bool register_python_module_object(PyObject *, PyTypeObject *);
#name "(" args ")\n--\n\n" doc \
}
-#define PYTHON_VOID_WRAPPER_DEF(name, args, flags, doc) \
- { \
- #name, (PyCFunction)py_return_none, \
- flags, \
- #name "(" args ")\n--\n\n" doc \
+#define PYTHON_WRAPPER_DEF_WITH(name, args, flags, defcb, doc) \
+ { \
+ #name, (PyCFunction)defcb, \
+ flags, \
+ #name "(" args ")\n--\n\n" doc \
}
-#define PYTHON_FALSE_WRAPPER_DEF(name, args, flags, doc)\
- { \
- #name, (PyCFunction)py_return_false, \
- flags, \
- #name "(" args ")\n--\n\n" doc \
- }
+#define PYTHON_VOID_WRAPPER_DEF(name, args, flags, doc) \
+ PYTHON_WRAPPER_DEF_WITH(name, args, flags, py_return_none, doc)
-#define PYTHON_TRUE_WRAPPER_DEF(name, args, flags, doc)\
- { \
- #name, (PyCFunction)py_return_true, \
- flags, \
- #name "(" args ")\n--\n\n" doc \
- }
+#define PYTHON_FALSE_WRAPPER_DEF(name, args, flags, doc) \
+ PYTHON_WRAPPER_DEF_WITH(name, args, flags, py_return_false, doc)
+
+#define PYTHON_TRUE_WRAPPER_DEF(name, args, flags, doc) \
+ PYTHON_WRAPPER_DEF_WITH(name, args, flags, py_return_true, doc)
/**
* Il ne semble pas exister de moyen de déterminer
@@ -158,6 +155,34 @@ bool register_python_module_object(PyObject *, PyTypeObject *);
#define APPLY_ABSTRACT_FLAG(tp) tp->tp_new = PyBaseObject_Type.tp_new
+/* Accompagne la création d'une instance dérivée en Python. */
+PyObject *python_constructor_with_dynamic_gtype(PyTypeObject *, GType, PyObject *, PyObject *);
+
+/* Accompagne la création d'une instance dérivée en Python. */
+PyObject *python_abstract_constructor_with_dynamic_gtype(PyTypeObject *, GType, GClassInitFunc, PyObject *, PyObject *);
+
+
+#define CREATE_DYN_CONSTRUCTOR(pyname, gbase) \
+static PyObject *py_ ## pyname ## _new(PyTypeObject *, PyObject *, PyObject *); \
+static PyObject *py_ ## pyname ## _new(PyTypeObject *type, PyObject *args, PyObject *kwds) \
+{ \
+ PyObject *result; /* Objet à retourner */ \
+ result = python_constructor_with_dynamic_gtype(type, gbase, args, kwds); \
+ return result; \
+}
+
+
+#define CREATE_DYN_ABSTRACT_CONSTRUCTOR(pyname, gbase, cinit) \
+static PyObject *py_ ## pyname ## _new(PyTypeObject *, PyObject *, PyObject *); \
+static PyObject *py_ ## pyname ## _new(PyTypeObject *type, PyObject *args, PyObject *kwds) \
+{ \
+ PyObject *result; /* Objet à retourner */ \
+ result = python_abstract_constructor_with_dynamic_gtype(type, gbase, (GClassInitFunc)cinit, \
+ args, kwds); \
+ return result; \
+}
+
+
/* Marque l'interdiction d'une instanciation depuis Python. */
PyObject *no_python_constructor_allowed(PyTypeObject *, PyObject *, PyObject *);
@@ -200,16 +225,13 @@ PyTypeObject *define_python_dynamic_type(const PyTypeObject *);
/* Enregistre correctement une surcouche de conversion GObject. */
-bool _register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObject *, ...);
-
-#define register_class_for_pygobject(dict, gtype, type, base) \
- _register_class_for_pygobject(dict, gtype, type, base, NULL)
+bool register_class_for_pygobject(PyObject *, GType, PyTypeObject *);
/* Enregistre correctement une interface GObject pour Python. */
bool register_interface_for_pygobject(PyObject *, GType, PyTypeObject *, const GInterfaceInfo *);
/* Enregistre un type Python dérivant d'un type GLib dynamique. */
-bool register_class_for_dynamic_pygobject(GType, PyTypeObject *, PyTypeObject *);
+bool register_class_for_dynamic_pygobject(GType, PyTypeObject *);
/* Fait suivre à la partie GObject une initialisation nouvelle. */
int forward_pygobjet_init(PyObject *);
@@ -220,12 +242,36 @@ int convert_to_gtype(PyObject *, void *);
/* Tente de convertir en instance GObject. */
int convert_to_gobject(PyObject *, void *);
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Tente de convertir en instance de composant GTK. */
int convert_to_gtk_widget(PyObject *, void *);
/* Tente de convertir en instance de conteneur GTK. */
int convert_to_gtk_container(PyObject *, void *);
+#endif
+
+
+#if !defined(INCLUDE_GTK_SUPPORT) && !defined(HOMEMADE_RGBA)
+
+# define HOMEMADE_RGBA
+
+/**
+ * Copie depuis /usr/include/gtk-3.0/gdk/gdkrgba.h
+ */
+typedef struct _GdkRGBA
+{
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble alpha;
+
+} GdkRGBA;
+
+#endif
+
+
/* Construit un objet Python pour une couleur RGBA. */
PyObject *create_gdk_rgba(const GdkRGBA *);
@@ -261,6 +307,41 @@ int convert_to_gdk_rgba(PyObject *, void *);
})
+#define TRANSLATE_NUMERIC_FIELD(dict, base, field) \
+ ({ \
+ PyObject *__attrib; \
+ __attrib = PyLong_FromUnsignedLongLong(base->field); \
+ Py_INCREF(__attrib); \
+ ADD_FIELD_TRANSLATION(dict, #field, __attrib); \
+ })
+
+
+#define RETRIEVE_NUMERIC_FIELD(dict, base, field) \
+ ({ \
+ bool __status; \
+ PyObject *__attrib; \
+ __status = false; \
+ __attrib = PyDict_GetItemString(dict, #field); \
+ if (__attrib != NULL && PyLong_Check(__attrib)) \
+ { \
+ base->field = PyLong_AsUnsignedLongLong(__attrib); \
+ __status = (PyErr_Occurred() == NULL); \
+ } \
+ __status; \
+ })
+
+
+#define TRANSLATE_BYTES_FIELD(dict, base, field, len) \
+ ({ \
+ void *__data; \
+ PyObject *__attrib; \
+ __data = (void *)&base->field; \
+ __attrib = PyBytes_FromStringAndSize(__data, len); \
+ Py_INCREF(__attrib); \
+ ADD_FIELD_TRANSLATION(dict, #field, __attrib); \
+ })
+
+
#define TRANSLATE_STRING_FIELD(dict, base, field) \
({ \
PyObject *__attrib; \
@@ -308,20 +389,46 @@ int convert_to_gdk_rgba(PyObject *, void *);
})
/* Officialise un groupe de constantes avec sémentique. */
-bool _attach_constants_group(const char *, PyObject *, bool, const char *, PyObject *, const char *);
-
-#define attach_constants_group_to_type(type, flags, name, values, doc) \
- _attach_constants_group(type->tp_name, type->tp_dict, flags, name, values, doc)
-
-#define attach_constants_group_to_module(mod, flags, name, values, doc) \
- ({ \
- bool __result; \
- const char *__owner; \
- PyObject *__dict; \
- __owner = PyModule_GetName(mod); \
- __dict = PyModule_GetDict(mod); \
- __result = _attach_constants_group(__owner, __dict, flags, name, values, doc); \
- __result; \
+PyObject *_attach_constants_group(const char *, PyObject *, bool, const char *, PyObject *, const char *);
+
+#define attach_constants_group_to_type(type, flags, name, values, doc) \
+ ({ \
+ bool __result; \
+ PyObject *__new; \
+ __new = _attach_constants_group(type->tp_name, type->tp_dict, flags, name, values, \
+ doc); \
+ __result = (__new != NULL); \
+ Py_XDECREF(__new); \
+ __result; \
+ })
+
+#define attach_constants_group_to_module(mod, flags, name, values, doc) \
+ ({ \
+ bool __result; \
+ const char *__owner; \
+ PyObject *__dict; \
+ PyObject *__new; \
+ __owner = PyModule_GetName(mod); \
+ __dict = PyModule_GetDict(mod); \
+ __new = _attach_constants_group(__owner, __dict, flags, name, values, doc); \
+ __result = (__new != NULL); \
+ Py_XDECREF(__new); \
+ __result; \
+ })
+
+/* Officialise un groupe de constantes avec lien GLib. */
+PyObject *_attach_constants_group_with_pyg_enum(const char *, PyObject *, bool, const char *, PyObject *, const char *, GType);
+
+
+#define attach_constants_group_to_type_with_pyg_enum(type, flags, name, values, doc, gtype) \
+ ({ \
+ bool __result; \
+ PyObject *__new; \
+ __new = _attach_constants_group_with_pyg_enum(type->tp_name, type->tp_dict, flags, \
+ name, values, doc, gtype); \
+ __result = (__new != NULL); \
+ Py_XDECREF(__new); \
+ __result; \
})
/* Traduit une valeur constante C en équivalent Python. */
diff --git a/plugins/pychrysalide/mangling/Makefile.am b/plugins/pychrysalide/mangling/Makefile.am
index bec4baf..640e420 100644
--- a/plugins/pychrysalide/mangling/Makefile.am
+++ b/plugins/pychrysalide/mangling/Makefile.am
@@ -1,23 +1,14 @@
noinst_LTLIBRARIES = libpychrysamangling.la
-libpychrysamangling_la_SOURCES = \
- demangler.h demangler.c \
+libpychrysamangling_la_SOURCES = \
+ demangler.h demangler.c \
module.h module.c
-libpychrysamangling_la_LIBADD =
-
-libpychrysamangling_la_LDFLAGS =
+libpychrysamangling_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysamangling_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/mangling/demangler.c b/plugins/pychrysalide/mangling/demangler.c
index 87a19dc..fb90dca 100644
--- a/plugins/pychrysalide/mangling/demangler.c
+++ b/plugins/pychrysalide/mangling/demangler.c
@@ -25,6 +25,7 @@
#include "demangler.h"
+#include <malloc.h>
#include <pygobject.h>
@@ -41,6 +42,9 @@
+/* Fournit la désignation interne du décodeur de désignations. */
+static PyObject *py_compiler_demangler_get_key(PyObject *, void *);
+
/* Tente de décoder une chaîne de caractères donnée en type. */
static PyObject *py_compiler_demangler_decode_type(PyObject *, PyObject *);
@@ -51,6 +55,53 @@ static PyObject *py_compiler_demangler_decode_routine(PyObject *, PyObject *);
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la désignation interne du décodeur de désignations. *
+* *
+* Retour : Simple chaîne de caractères. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_compiler_demangler_get_key(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GCompDemangler *demangler; /* Version GLib de l'opérande */
+ char *key; /* Désignation du décodeur */
+
+#define COMPILER_DEMANGLER_KEY_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ key, py_compiler_demangler, \
+ "Provide the small name used to identify the demangler," \
+ " as a code string." \
+)
+
+ demangler = G_COMP_DEMANGLER(pygobject_get(self));
+ assert(demangler != NULL);
+
+ key = g_compiler_demangler_get_key(demangler);
+
+ if (key != NULL)
+ {
+ result = PyUnicode_FromString(key);
+ free(key);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = décodeur à solliciter pour l'opération. *
* args = chaîne de caractères à décoder. *
* *
@@ -184,6 +235,7 @@ PyTypeObject *get_python_compiler_demangler_type(void)
};
static PyGetSetDef py_comp_demangler_getseters[] = {
+ COMPILER_DEMANGLER_KEY_ATTRIB,
{ NULL }
};
@@ -212,7 +264,7 @@ PyTypeObject *get_python_compiler_demangler_type(void)
* *
* Paramètres : module = module dont la définition est à compléter. *
* *
-* Description : Prend en charge l'objet 'pychrysalide.mangling.DexDemangler'.*
+* Description : Prend en charge l'objet 'pychrysalide....CompDemangler'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -234,7 +286,7 @@ bool ensure_python_compiler_demangler_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_COMP_DEMANGLER, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_COMP_DEMANGLER, type))
return false;
}
diff --git a/plugins/pychrysalide/mangling/demangler.h b/plugins/pychrysalide/mangling/demangler.h
index 0c31f7c..496aa21 100644
--- a/plugins/pychrysalide/mangling/demangler.h
+++ b/plugins/pychrysalide/mangling/demangler.h
@@ -34,7 +34,7 @@
/* Fournit un accès à une définition de type à diffuser. */
PyTypeObject *get_python_compiler_demangler_type(void);
-/* Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. */
+/* Prend en charge l'objet 'pychrysalide.mangling.CompDemangler'. */
bool ensure_python_compiler_demangler_is_registered(void);
diff --git a/plugins/pychrysalide/plugins/Makefile.am b/plugins/pychrysalide/plugins/Makefile.am
index 8a0d4c9..bb9ed5d 100644
--- a/plugins/pychrysalide/plugins/Makefile.am
+++ b/plugins/pychrysalide/plugins/Makefile.am
@@ -1,25 +1,16 @@
noinst_LTLIBRARIES = libpychrysaplugins.la
-libpychrysaplugins_la_SOURCES = \
- constants.h constants.c \
- plugin.h plugin.c \
- module.h module.c \
+libpychrysaplugins_la_SOURCES = \
+ constants.h constants.c \
+ plugin.h plugin.c \
+ module.h module.c \
translate.h translate.c
-libpychrysaplugins_la_LIBADD =
-
-libpychrysaplugins_la_LDFLAGS =
+libpychrysaplugins_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaplugins_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/plugins/pychrysalide/plugins/plugin.c b/plugins/pychrysalide/plugins/plugin.c
index bd9cdfe..b013345 100644
--- a/plugins/pychrysalide/plugins/plugin.c
+++ b/plugins/pychrysalide/plugins/plugin.c
@@ -51,21 +51,31 @@
/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Accompagne la création d'une instance dérivée en Python. */
-static PyObject *py_plugin_module_new(PyTypeObject *, PyObject *, PyObject *);
-
/* Initialise la classe des greffons d'extension. */
static void py_plugin_module_init_gclass(GPluginModuleClass *, gpointer);
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(plugin_module, G_TYPE_PLUGIN_MODULE, py_plugin_module_init_gclass);
+
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds);
/* Encadre une étape de la vie d'un greffon. */
static bool py_plugin_module_manage_wrapper(GPluginModule *);
+/* Assiste la désactivation d'un greffon. */
+static bool py_plugin_module_exit(GPluginModule *);
+
/* Accompagne la fin du chargement des modules natifs. */
static void py_plugin_module_notify_plugins_loaded_wrapper(GPluginModule *, PluginAction);
+/* Fournit le nom brut associé au greffon par défaut. */
+static PyObject *py_plugin_module_get_modname_by_default(PyObject *, PyObject *);
+
+/* Fournit le nom brut associé au greffon. */
+static char *py_plugin_module_get_modname_wrapper(const GPluginModule *);
+
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Complète une liste de resources pour thème. */
static void py_plugin_module_include_theme_wrapper(const GPluginModule *, PluginAction, gboolean, char ***, size_t *);
@@ -75,6 +85,8 @@ static void py_plugin_module_notify_panel_creation_wrapper(const GPluginModule *
/* Rend compte d'un affichage ou d'un retrait de panneau. */
static void py_plugin_module_notify_panel_docking_wrapper(const GPluginModule *, PluginAction, GPanelItem *, bool);
+#endif
+
/* Procède à une opération liée à un contenu binaire. */
static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
@@ -98,42 +110,6 @@ static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *
-/* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
-
-
-/* Ligne de représentation de code binaire (instance) */
-struct _GPythonPlugin
-{
- GPluginModule parent; /* Instance parente */
-
-};
-
-
-/* Ligne de représentation de code binaire (classe) */
-struct _GPythonPluginClass
-{
- GPluginModuleClass parent; /* Classe parente */
-
-};
-
-
-/* Initialise la classe des greffons Python. */
-static void g_python_plugin_class_init(GPythonPluginClass *);
-
-/* Initialise l'instance d'un greffon Python. */
-static void g_python_plugin_init(GPythonPlugin *);
-
-/* Supprime toutes les références externes. */
-static void g_python_plugin_dispose(GPythonPlugin *);
-
-/* Description : Procède à la libération totale de la mémoire. */
-static void g_python_plugin_finalize(GPythonPlugin *);
-
-/* Fournit le nom brut associé au greffon. */
-static char *g_python_plugin_get_modname(const GPythonPlugin *);
-
-
-
/* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
@@ -161,69 +137,6 @@ static PyObject *py_plugin_module_get_interface(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type du nouvel objet à mettre en place. *
-* args = éventuelle liste d'arguments. *
-* kwds = éventuel dictionnaire de valeurs mises à disposition. *
-* *
-* Description : Accompagne la création d'une instance dérivée en Python. *
-* *
-* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_plugin_module_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Objet à retourner */
- PyTypeObject *base; /* Type de base à dériver */
- bool first_time; /* Evite les multiples passages*/
- GType gtype; /* Nouveau type de processeur */
- bool status; /* Bilan d'un enregistrement */
-
- /* Validations diverses */
-
- base = get_python_plugin_module_type();
-
- if (type == base)
- {
- result = NULL;
- PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
- goto exit;
- }
-
- /* Mise en place d'un type dédié */
-
- first_time = (g_type_from_name(type->tp_name) == 0);
-
- gtype = build_dynamic_type(G_TYPE_PYTHON_PLUGIN, type->tp_name,
- (GClassInitFunc)py_plugin_module_init_gclass, NULL, NULL);
-
- if (first_time)
- {
- status = register_class_for_dynamic_pygobject(gtype, type, base);
-
- if (!status)
- {
- result = NULL;
- goto exit;
- }
-
- }
-
- /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
-
- result = PyType_GenericNew(type, args, kwds);
-
- exit:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : class = classe à initialiser. *
* unused = données non utilisées ici. *
* *
@@ -239,13 +152,17 @@ static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unu
{
class->init = NULL;
class->manage = py_plugin_module_manage_wrapper;
- class->exit = NULL;
+ class->exit = py_plugin_module_exit;
class->plugins_loaded = py_plugin_module_notify_plugins_loaded_wrapper;
+ class->get_modname = py_plugin_module_get_modname_wrapper;
+
+#ifdef INCLUDE_GTK_SUPPORT
class->include_theme = py_plugin_module_include_theme_wrapper;
class->notify_panel = py_plugin_module_notify_panel_creation_wrapper;
class->notify_docking = py_plugin_module_notify_panel_docking_wrapper;
+#endif
class->handle_content = py_plugin_module_handle_binary_content_wrapper;
class->handle_loaded = py_plugin_module_handle_loaded_content_wrapper;
@@ -498,6 +415,51 @@ static bool py_plugin_module_manage_wrapper(GPluginModule *plugin)
/******************************************************************************
* *
* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Assiste la désactivation d'un greffon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_plugin_module_exit(GPluginModule *plugin)
+{
+ bool result; /* Bilan à faire remonter */
+ plugin_interface *final; /* Interface finale conservée */
+
+ result = true;
+
+ final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
+
+ if (final != NULL)
+ {
+ if (final->name != NULL) free(final->name);
+ if (final->desc != NULL) free(final->desc);
+ if (final->version != NULL) free(final->version);
+ if (final->url != NULL) free(final->url);
+
+ assert(final->required_count == 1);
+
+ if (final->required != NULL)
+ free(final->required);
+
+ if (final->actions != NULL)
+ free(final->actions);
+
+ free(final);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
* action = type d'action attendue. *
* *
* Description : Accompagne la fin du chargement des modules natifs. *
@@ -555,6 +517,103 @@ static void py_plugin_module_notify_plugins_loaded_wrapper(GPluginModule *plugin
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Fournit le nom brut associé au greffon par défaut. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_plugin_module_get_modname_by_default(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GPluginModule *plugin; /* Version native du greffon */
+ char *path; /* Chemin à traiter */
+
+ plugin = G_PLUGIN_MODULE(pygobject_get(self));
+
+ path = strdup(g_plugin_module_get_filename(plugin));
+
+ result = PyUnicode_FromString(basename(path));
+
+ free(path);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à valider. *
+* *
+* Description : Fournit le nom brut associé au greffon. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_plugin_module_get_modname_wrapper(const GPluginModule *plugin)
+{
+ char *result; /* Désignation brute à renvoyer*/
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan d'exécution */
+
+#define PLUGIN_MODULE_GET_MODNAME_WRAPPER PYTHON_WRAPPER_DEF_WITH \
+( \
+ _get_modname, "$self, /", \
+ METH_VARARGS, py_plugin_module_get_modname_by_default, \
+ "(Abstract) method providing the raw module name of the plugin.\n" \
+ " loaded.\n" \
+ "\n" \
+ "The result should be a short string value.\n" \
+ "\n" \
+ "A default implementation builds the module name from the Python" \
+ " script filename." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ if (has_python_method(pyobj, "_get_modname"))
+ {
+ pyret = run_python_method(pyobj, "_get_modname", NULL);
+
+ if (!PyUnicode_Check(pyret))
+ g_plugin_module_log_variadic_message(plugin, LMT_ERROR,
+ _("The returned raw name must be a string"));
+
+ else
+ result = strdup(PyUnicode_DATA(pyret));
+
+ Py_XDECREF(pyret);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+#ifdef INCLUDE_GTK_SUPPORT
+
+
+/******************************************************************************
+* *
* Paramètres : plugin = greffon à manipuler. *
* action = type d'action attendue. *
* dark = indique une préférence pour la variante foncée. *
@@ -783,6 +842,9 @@ static void py_plugin_module_notify_panel_docking_wrapper(const GPluginModule *p
}
+#endif
+
+
/******************************************************************************
* *
* Paramètres : plugin = greffon à manipuler. *
@@ -1300,262 +1362,6 @@ static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *
/* ---------------------------------------------------------------------------------- */
-/* INTERFACE INTERNE POUR GREFFONS PYTHON */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini par la GLib pour le greffon Python. */
-G_DEFINE_TYPE(GPythonPlugin, g_python_plugin, G_TYPE_PLUGIN_MODULE);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des greffons Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_class_init(GPythonPluginClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
- GPluginModuleClass *plugin; /* Version parente de la classe*/
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_python_plugin_dispose;
- object->finalize = (GObjectFinalizeFunc)g_python_plugin_finalize;
-
- plugin = G_PLUGIN_MODULE_CLASS(klass);
-
- plugin->get_modname = (pg_get_modname_fc)g_python_plugin_get_modname;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance à initialiser. *
-* *
-* Description : Initialise l'instance d'un greffon Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_init(GPythonPlugin *plugin)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_dispose(GPythonPlugin *plugin)
-{
-#if 0
- PyThreadState *tstate; /* Contexte d'environnement */
-
- /**
- * Cf. https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock
- *
- * Cependant, comme on se trouve à priori dans le thread principal de l'interpréteur,
- * PyGILState_Ensure() ne pose aucun verrou. Ce qui aboutit à la situation suivante :
- *
- * Fatal Python error: drop_gil: GIL is not locked
- *
- * On peut forcer les choses avec PyEval_AcquireLock(), mais cette fonction est marquée
- * comme dépréciée depuis Python 3.2.
- *
- * Donc on choisit les alternatives officielles.
- *
- * Cependant, PyThreadState_Get() renvoit l'erreur suivante :
- *
- * Fatal Python error: PyThreadState_Get: no current thread
- *
- * Donc on se rabat sur une sauvegarde, qui n'est initialisée que lorsque l'interpréteur
- * est intégré dans l'éditeur.
- */
-
- tstate = get_pychrysalide_main_tstate();
-
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
-
- if (tstate != NULL)
- PyEval_SaveThread();
-#endif
-
- G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_finalize(GPythonPlugin *plugin)
-{
- plugin_interface *final; /* Interface finale conservée */
-
- final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
-
- if (final != NULL)
- {
- if (final->name != NULL) free(final->name);
- if (final->desc != NULL) free(final->desc);
- if (final->version != NULL) free(final->version);
- if (final->url != NULL) free(final->url);
-
- assert(final->required_count == 1);
-
- if (final->required != NULL)
- free(final->required);
-
- if (final->actions != NULL)
- free(final->actions);
-
- free(final);
-
- }
-
- G_OBJECT_CLASS(g_python_plugin_parent_class)->finalize(G_OBJECT(plugin));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à valider. *
-* *
-* Description : Fournit le nom brut associé au greffon. *
-* *
-* Retour : Désignation brute du greffon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_python_plugin_get_modname(const GPythonPlugin *plugin)
-{
- char *result; /* Désignation brute à renvoyer*/
- char *path; /* Chemin à traiter */
-
- path = strdup(g_plugin_module_get_filename(G_PLUGIN_MODULE(plugin)));
-
- result = strdup(basename(path));
-
- free(path);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : modname = nom du module à charger. *
-* filename = chemin d'accès au code Python à charger. *
-* *
-* Description : Crée un greffon à partir de code Python. *
-* *
-* Retour : Adresse de la structure mise en place ou NULL si erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
-{
- GPythonPlugin *result; /* Structure à retourner */
- PyObject *name; /* Chemin d'accès pour Python */
- PyObject *module; /* Script Python chargé */
- PyObject *dict; /* Dictionnaire associé */
- PyObject *class; /* Classe à instancier */
- PyObject *instance; /* Instance Python du greffon */
-
- name = PyUnicode_FromString(modname);
- if (name == NULL) goto bad_exit;
-
- module = PyImport_Import(name);
- Py_DECREF(name);
-
- if (module == NULL) goto no_import;
-
- dict = PyModule_GetDict(module);
- class = PyDict_GetItemString(dict, "AutoLoad");
-
- if (class == NULL) goto no_class;
- if (!PyType_Check(class->ob_type)) goto no_class;
-
- instance = PyObject_CallFunction(class, NULL);
- if (instance == NULL) goto no_instance;
-
- result = G_PYTHON_PLUGIN(pygobject_get(instance));
-
- G_PLUGIN_MODULE(result)->filename = strdup(filename);
-
- /**
- * L'instance Python et l'objet GLib résultante sont un même PyGObject.
- *
- * Donc pas besoin de toucher au comptage des références ici, la libération
- * se réalisera à la fin, quand l'objet GLib sera libéré.
- */
-
- Py_DECREF(module);
-
- return G_PLUGIN_MODULE(result);
-
- no_instance:
-
- log_pychrysalide_exception(_("An error occured when building the 'AutoLoad' instance"));
-
- no_class:
-
- if (class == NULL)
- log_plugin_simple_message(LMT_ERROR,
- _("An error occured when looking for the 'AutoLoad': item not found!"));
-
- no_import:
-
- Py_XDECREF(module);
-
- log_pychrysalide_exception(_("An error occured when importing '%s'"), modname);
-
- bad_exit:
-
- return NULL;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* MODULE PYTHON POUR LES SCRIPTS */
/* ---------------------------------------------------------------------------------- */
@@ -1865,9 +1671,12 @@ PyTypeObject *get_python_plugin_module_type(void)
static PyMethodDef py_plugin_module_methods[] = {
PLUGIN_MODULE_MANAGE_WRAPPER,
PLUGIN_MODULE_NOTIFY_PLUGINS_LOADED_WRAPPER,
+ PLUGIN_MODULE_GET_MODNAME_WRAPPER,
+#ifdef INCLUDE_GTK_SUPPORT
PLUGIN_MODULE_INCLUDE_THEME_WRAPPER,
PLUGIN_MODULE_ON_PANEL_CREATION_WRAPPER,
PLUGIN_MODULE_ON_PANEL_DOCKING_WRAPPER,
+#endif
PLUGIN_MODULE_HANDLE_BINARY_CONTENT_WRAPPER,
PLUGIN_MODULE_HANDLE_LOADED_CONTENT_WRAPPER,
PLUGIN_MODULE_HANDLE_BINARY_FORMAT_ANALYSIS_WRAPPER,
@@ -1938,7 +1747,7 @@ bool ensure_python_plugin_module_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PYTHON_PLUGIN, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_PLUGIN_MODULE, type))
return false;
if (!define_plugin_module_constants(type))
@@ -1949,3 +1758,80 @@ bool ensure_python_plugin_module_is_registered(void)
return true;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : modname = nom du module à charger. *
+* filename = chemin d'accès au code Python à charger. *
+* *
+* Description : Crée un greffon à partir de code Python. *
+* *
+* Retour : Adresse de la structure mise en place ou NULL si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPluginModule *create_python_plugin(const char *modname, const char *filename)
+{
+ GPluginModule *result; /* Structure à retourner */
+ PyObject *name; /* Chemin d'accès pour Python */
+ PyObject *module; /* Script Python chargé */
+ PyObject *dict; /* Dictionnaire associé */
+ PyObject *class; /* Classe à instancier */
+ PyObject *instance; /* Instance Python du greffon */
+
+ name = PyUnicode_FromString(modname);
+ if (name == NULL) goto bad_exit;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+
+ if (module == NULL) goto no_import;
+
+ dict = PyModule_GetDict(module);
+ class = PyDict_GetItemString(dict, "AutoLoad");
+
+ if (class == NULL) goto no_class;
+ if (!PyType_Check(class->ob_type)) goto no_class;
+
+ instance = PyObject_CallFunction(class, NULL);
+ if (instance == NULL) goto no_instance;
+
+ result = G_PLUGIN_MODULE(pygobject_get(instance));
+
+ result->filename = strdup(filename);
+
+ /**
+ * L'instance Python et l'objet GLib résultante sont un même PyGObject.
+ *
+ * Donc pas besoin de toucher au comptage des références ici, la libération
+ * se réalisera à la fin, quand l'objet GLib sera libéré.
+ */
+
+ Py_DECREF(module);
+
+ return result;
+
+ no_instance:
+
+ log_pychrysalide_exception(_("An error occured when building the 'AutoLoad' instance"));
+
+ no_class:
+
+ if (class == NULL)
+ log_plugin_simple_message(LMT_ERROR,
+ _("An error occured when looking for the 'AutoLoad': item not found!"));
+
+ no_import:
+
+ Py_XDECREF(module);
+
+ log_pychrysalide_exception(_("An error occured when importing '%s'"), modname);
+
+ bad_exit:
+
+ return NULL;
+
+}
diff --git a/plugins/pychrysalide/plugins/plugin.h b/plugins/pychrysalide/plugins/plugin.h
index ff805f4..ad54b8e 100644
--- a/plugins/pychrysalide/plugins/plugin.h
+++ b/plugins/pychrysalide/plugins/plugin.h
@@ -35,41 +35,15 @@
-/* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
-
-
-#define G_TYPE_PYTHON_PLUGIN (g_python_plugin_get_type())
-#define G_PYTHON_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PYTHON_PLUGIN, GPythonPlugin))
-#define G_IS_PYTHON_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PYTHON_PLUGIN))
-#define G_PYTHON_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PYTHON_PLUGIN, GPythonPluginClass))
-#define G_IS_PYTHON_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PYTHON_PLUGIN))
-#define G_PYTHON_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PYTHON_PLUGIN, GPythonPluginClass))
-
-
-/* Ligne de représentation de code binaire (instance) */
-typedef struct _GPythonPlugin GPythonPlugin;
-
-/* Ligne de représentation de code binaire (classe) */
-typedef struct _GPythonPluginClass GPythonPluginClass;
-
-
-/* Indique le type défini par la GLib pour le greffon Python. */
-GType g_python_plugin_get_type(void);
-
-/* Crée un greffon à partir de code Python. */
-GPluginModule *g_python_plugin_new(const char *, const char *);
-
-
-
-/* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
-
-
/* Fournit un accès à une définition de type à diffuser. */
PyTypeObject *get_python_plugin_module_type(void);
/* Prend en charge l'objet 'pychrysalide.plugins.PluginModule'. */
bool ensure_python_plugin_module_is_registered(void);
+/* Crée un greffon à partir de code Python. */
+GPluginModule *create_python_plugin(const char *, const char *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_PLUGINS_PLUGIN_H */
diff --git a/plugins/pychrysalide/weak.h b/plugins/pychrysalide/weak.h
index 01885b0..767873f 100644
--- a/plugins/pychrysalide/weak.h
+++ b/plugins/pychrysalide/weak.h
@@ -26,10 +26,10 @@
#define _PLUGINS_PYCHRYSALIDE_WEAK_H
-#include <gtkext/gtkstatusstack.h>
-
+#include <glibext/notifier.h>
+#if 0
/* Démarre le suivi d'une nouvelle activité. */
activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long) __attribute__((weak));
@@ -44,7 +44,7 @@ void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, uns
/* Met fin au suivi d'une activité donnée. */
void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t) __attribute__((weak));
-
+#endif
#endif /* _PLUGINS_PYCHRYSALIDE_WEAK_H */
diff --git a/plugins/python/cglimpse/panel.py b/plugins/python/cglimpse/panel.py
index a195b0d..e2dc035 100644
--- a/plugins/python/cglimpse/panel.py
+++ b/plugins/python/cglimpse/panel.py
@@ -118,7 +118,8 @@ class CGlimpsePanel(PanelItem, UpdatablePanel):
assert(uid == 0)
- self.switch_to_updating_mask()
+ # Reduce the rendering concurrency between the GTK main loop and this thread
+ #self.switch_to_updating_mask()
def _process(self, uid, status, id, data):
@@ -137,7 +138,8 @@ class CGlimpsePanel(PanelItem, UpdatablePanel):
assert(uid == 0)
- self.switch_to_updated_content()
+ # Reduce the rendering concurrency between the GTK main loop and this thread
+ # self.switch_to_updated_content()
def _clean_data(self, uid, data):
diff --git a/plugins/python/scripting/core.py b/plugins/python/scripting/core.py
index ff912ed..135edb4 100644
--- a/plugins/python/scripting/core.py
+++ b/plugins/python/scripting/core.py
@@ -1,4 +1,7 @@
+import gi
+gi.require_version('Gtk', '3.0')
+
from gi.repository import GLib, Gtk
import os
diff --git a/plugins/readdex/Makefile.am b/plugins/readdex/Makefile.am
index b21f855..b2099fb 100644
--- a/plugins/readdex/Makefile.am
+++ b/plugins/readdex/Makefile.am
@@ -15,13 +15,15 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN'
endif
-libreaddex_la_SOURCES = \
- class.h class.c \
- code.h code.c \
- header.h header.c \
- ids.h ids.c \
+libreaddex_la_SOURCES = \
+ class.h class.c \
+ code.h code.c \
+ header.h header.c \
+ ids.h ids.c \
reader.h reader.c
+libreaddex_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libreaddex_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -33,8 +35,3 @@ libreaddex_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libreaddex_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/readdex/class.h b/plugins/readdex/class.h
index c7c34b0..a2c2bee 100644
--- a/plugins/readdex/class.h
+++ b/plugins/readdex/class.h
@@ -26,7 +26,7 @@
#include <format/preload.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
#include <plugins/dex/format.h>
diff --git a/plugins/readdex/ids.h b/plugins/readdex/ids.h
index 3a902cd..85495d1 100644
--- a/plugins/readdex/ids.h
+++ b/plugins/readdex/ids.h
@@ -26,7 +26,7 @@
#include <format/preload.h>
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
#include <plugins/dex/format.h>
diff --git a/plugins/readelf/Makefile.am b/plugins/readelf/Makefile.am
index 0ca002b..7e662ee 100644
--- a/plugins/readelf/Makefile.am
+++ b/plugins/readelf/Makefile.am
@@ -15,13 +15,15 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN'
endif
-libreadelf_la_SOURCES = \
- header.h header.c \
- program.h program.c \
- reader.h reader.c \
- section.h section.c \
+libreadelf_la_SOURCES = \
+ header.h header.c \
+ program.h program.c \
+ reader.h reader.c \
+ section.h section.c \
strtab.h strtab.c
+libreadelf_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libreadelf_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -29,11 +31,7 @@ libreadelf_la_LDFLAGS = \
-L$(top_srcdir)/plugins/fmtp/.libs -lfmtp \
$(RUN_PATH)
+
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libreadelf_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/readmc/Makefile.am b/plugins/readmc/Makefile.am
index fa13fb2..51a8552 100644
--- a/plugins/readmc/Makefile.am
+++ b/plugins/readmc/Makefile.am
@@ -15,14 +15,16 @@ RUN_PATH = -Wl,-rpath,'$$ORIGIN'
endif
-libreadmc_la_SOURCES = \
- header.h header.c \
- reader.h reader.c \
- text.h text.c \
- v21.h v21.c \
- v23.h v23.c \
+libreadmc_la_SOURCES = \
+ header.h header.c \
+ reader.h reader.c \
+ text.h text.c \
+ v21.h v21.c \
+ v23.h v23.c \
v24.h v24.c
+libreadmc_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libreadmc_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -34,8 +36,3 @@ libreadmc_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libreadmc_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/ropgadgets/Makefile.am b/plugins/ropgadgets/Makefile.am
index f23e054..bec050e 100644
--- a/plugins/ropgadgets/Makefile.am
+++ b/plugins/ropgadgets/Makefile.am
@@ -22,6 +22,8 @@ libropgadgets_la_SOURCES = \
plugin.h plugin.c \
select.h select.c
+libropgadgets_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libropgadgets_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -32,8 +34,3 @@ libropgadgets_la_LDFLAGS = \
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libropgadgets_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/ropgadgets/plugin.c b/plugins/ropgadgets/plugin.c
index 836717c..938a04c 100644
--- a/plugins/ropgadgets/plugin.c
+++ b/plugins/ropgadgets/plugin.c
@@ -24,7 +24,6 @@
#include "plugin.h"
-#include <config.h>
#include <i18n.h>
@@ -36,7 +35,7 @@
#include "select.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c
index a45f043..c0cf08d 100644
--- a/plugins/ropgadgets/select.c
+++ b/plugins/ropgadgets/select.c
@@ -35,10 +35,12 @@
#include <i18n.h>
+#include <analysis/binary.h>
#include <analysis/contents/file.h>
#include <core/global.h>
#include <common/cpp.h>
#include <common/extstr.h>
+#include <core/columns.h>
#include <core/processors.h>
#include <format/known.h>
#include <gui/core/global.h>
diff --git a/plugins/winordinals/Makefile.am b/plugins/winordinals/Makefile.am
index f9ff14f..592d38a 100644
--- a/plugins/winordinals/Makefile.am
+++ b/plugins/winordinals/Makefile.am
@@ -50,6 +50,8 @@ libwinordinals_la_SOURCES = \
libwinordinals_la_LIBADD = \
$(PYTHON3_LIBADD)
+libwinordinals_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
libwinordinals_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
@@ -62,8 +64,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libwinordinals_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/winordinals/assign.h b/plugins/winordinals/assign.h
index 20310d2..e88ee28 100644
--- a/plugins/winordinals/assign.h
+++ b/plugins/winordinals/assign.h
@@ -25,7 +25,7 @@
#define _PLUGINS_WINORDINALS_ASSIGN_H
-#include <gtkext/gtkstatusstack.h>
+#include <glibext/notifier.h>
#include <plugins/pe/format.h>
diff --git a/plugins/winordinals/core.c b/plugins/winordinals/core.c
index a16c400..bae2d6d 100644
--- a/plugins/winordinals/core.c
+++ b/plugins/winordinals/core.c
@@ -31,12 +31,12 @@
#include "assign.h"
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -67,7 +67,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
result = true;
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_winordinals_module_to_python_module();
diff --git a/plugins/winordinals/python/Makefile.am b/plugins/winordinals/python/Makefile.am
index a5f17a4..201650d 100644
--- a/plugins/winordinals/python/Makefile.am
+++ b/plugins/winordinals/python/Makefile.am
@@ -4,15 +4,10 @@ noinst_LTLIBRARIES = libwinordinalspython.la
libwinordinalspython_la_SOURCES = \
module.h module.c
-libwinordinalspython_la_LDFLAGS =
+libwinordinalspython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libwinordinalspython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/yaml/Makefile.am b/plugins/yaml/Makefile.am
index 9eee4ab..1165d7a 100644
--- a/plugins/yaml/Makefile.am
+++ b/plugins/yaml/Makefile.am
@@ -36,23 +36,24 @@ endif
libyaml_la_SOURCES = \
+ collection-int.h \
collection.h collection.c \
core.h core.c \
- line.h line.c \
node-int.h \
node.h node.c \
+ pair-int.h \
pair.h pair.c \
- reader.h reader.c \
- scalar.h scalar.c \
- tree.h tree.c
+ parser.h parser.c
libyaml_la_LIBADD = \
$(PYTHON3_LIBADD)
+libyaml_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBYAML_CFLAGS) -I$(top_srcdir)/src
+
libyaml_la_LDFLAGS = \
-avoid-version \
-L$(top_srcdir)/src/.libs -lchrysacore \
- $(RUN_PATH) $(PYTHON3_LDFLAGS)
+ $(RUN_PATH) $(LIBYAML_LIBS) $(PYTHON3_LDFLAGS)
devdir = $(includedir)/chrysalide/$(subdir)
@@ -60,8 +61,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libyaml_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/yaml/collection-int.h b/plugins/yaml/collection-int.h
new file mode 100644
index 0000000..453976d
--- /dev/null
+++ b/plugins/yaml/collection-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * collection-int.h - prototypes internes pour la définition d'un noeud YAML
+ *
+ * Copyright (C) 2019-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_YAML_COLLECTION_INT_H
+#define PLUGINS_YAML_COLLECTION_INT_H
+
+
+#include "collection.h"
+
+
+#include "node-int.h"
+
+
+
+/* Collection de noeuds au format YAML (instance) */
+struct _GYamlCollection
+{
+ GYamlNode parent; /* A laisser en premier */
+
+ bool is_seq; /* Nature de la collection */
+
+ GYamlNode **nodes; /* Sous-noeuds intégrés */
+ size_t count; /* Nombre de ces enfants */
+
+};
+
+/* Collection de noeuds au format YAML (classe) */
+struct _GYamlCollectionClass
+{
+ GYamlNodeClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une collection de noeuds YAML. */
+bool g_yaml_collection_create(GYamlCollection *, bool);
+
+
+
+#endif /* PLUGINS_YAML_COLLECTION_INT_H */
diff --git a/plugins/yaml/collection.c b/plugins/yaml/collection.c
index 376e894..cdc63d9 100644
--- a/plugins/yaml/collection.c
+++ b/plugins/yaml/collection.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * collection.h - collection de noeuds Yaml de type "sequence" ou "mapping"
+ * collection.h - collection de noeuds YAML de type "sequence" ou "mapping"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -27,34 +27,17 @@
#include <malloc.h>
-#include "node-int.h"
+#include "collection-int.h"
-/* Collection de noeuds au format Yaml (instance) */
-struct _GYamlCollection
-{
- GYamlNode parent; /* A laisser en premier */
-
- bool is_seq; /* Nature de la collection */
-
- GYamlNode **nodes; /* Sous-noeuds intégrés */
- size_t count; /* Nombre de ces enfants */
-
-};
-
-/* Collection de noeuds au format Yaml (classe) */
-struct _GYamlCollectionClass
-{
- GYamlNodeClass parent; /* A laisser en premier */
-
-};
+/* -------------------- DEFINITIONS PROPRES POUR LE SUPPORT YAML -------------------- */
-/* Initialise la classe des collections de noeuds Yaml. */
+/* Initialise la classe des collections de noeuds YAML. */
static void g_yaml_collection_class_init(GYamlCollectionClass *);
-/* Initialise une instance de collection de noeuds Yaml. */
+/* Initialise une instance de collection de noeuds YAML. */
static void g_yaml_collection_init(GYamlCollection *);
/* Supprime toutes les références externes. */
@@ -63,12 +46,22 @@ static void g_yaml_collection_dispose(GYamlCollection *);
/* Procède à la libération totale de la mémoire. */
static void g_yaml_collection_finalize(GYamlCollection *);
-/* Recherche les noeuds correspondant à un chemin. */
-static void g_yaml_collection_find_by_path(const GYamlCollection *, const char *, bool, GYamlNode ***, size_t *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Recherche le premier noeud correspondant à un chemin. */
+static GYamlNode *g_yaml_collection_find_first_by_path(GYamlCollection *, const char *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITIONS PROPRES POUR LE SUPPORT YAML */
+/* ---------------------------------------------------------------------------------- */
+
-/* Indique le type défini pour une collection de noeuds Yaml. */
+/* Indique le type défini pour une collection de noeuds YAML. */
G_DEFINE_TYPE(GYamlCollection, g_yaml_collection, G_TYPE_YAML_NODE);
@@ -76,7 +69,7 @@ G_DEFINE_TYPE(GYamlCollection, g_yaml_collection, G_TYPE_YAML_NODE);
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des collections de noeuds Yaml. *
+* Description : Initialise la classe des collections de noeuds YAML. *
* *
* Retour : - *
* *
@@ -96,7 +89,7 @@ static void g_yaml_collection_class_init(GYamlCollectionClass *klass)
node = G_YAML_NODE_CLASS(klass);
- node->find = (find_yaml_node_fc)g_yaml_collection_find_by_path;
+ node->find = (find_first_yaml_node_fc)g_yaml_collection_find_first_by_path;
}
@@ -105,7 +98,7 @@ static void g_yaml_collection_class_init(GYamlCollectionClass *klass)
* *
* Paramètres : collec = instance à initialiser. *
* *
-* Description : Initialise une instance de collection de noeuds Yaml. *
+* Description : Initialise une instance de collection de noeuds YAML. *
* *
* Retour : - *
* *
@@ -173,7 +166,7 @@ static void g_yaml_collection_finalize(GYamlCollection *collec)
* *
* Paramètres : seq = indique la nature de la future collection. *
* *
-* Description : Construit une collection de noeuds Yaml. *
+* Description : Construit une collection de noeuds YAML. *
* *
* Retour : Instance mise en place ou NULL en cas d'échec. *
* *
@@ -187,7 +180,34 @@ GYamlCollection *g_yaml_collection_new(bool seq)
result = g_object_new(G_TYPE_YAML_COLLEC, NULL);
- result->is_seq = seq;
+ if (!g_yaml_collection_create(result, seq))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = noeud d'arborescence YAML à initialiser pleinement. *
+* seq = indique la nature de la future collection. *
+* *
+* Description : Met en place une collection de noeuds YAML. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_yaml_collection_create(GYamlCollection *collec, bool seq)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ collec->is_seq = seq;
return result;
@@ -196,9 +216,9 @@ GYamlCollection *g_yaml_collection_new(bool seq)
/******************************************************************************
* *
-* Paramètres : collec = noeud d'arborescence Yaml à consulter. *
+* Paramètres : collec = noeud d'arborescence YAML à consulter. *
* *
-* Description : Indique la nature d'une collection Yaml. *
+* Description : Indique la nature d'une collection YAML. *
* *
* Retour : Nature de la collection. *
* *
@@ -219,10 +239,10 @@ bool g_yaml_collection_is_sequence(const GYamlCollection *collec)
/******************************************************************************
* *
-* Paramètres : collec = collection de noeuds Yaml à compléter. *
+* Paramètres : collec = collection de noeuds YAML à compléter. *
* node = noeud à rattacher. *
* *
-* Description : Ajoute un noeud à une collection de noeuds Yaml. *
+* Description : Ajoute un noeud à une collection de noeuds YAML. *
* *
* Retour : - *
* *
@@ -242,12 +262,12 @@ void g_yaml_collection_add_node(GYamlCollection *collec, GYamlNode *node)
/******************************************************************************
* *
-* Paramètres : collec = noeud d'arborescence Yaml à consulter. *
+* Paramètres : collec = noeud d'arborescence YAML à consulter. *
* count = taille de la liste constituée. [OUT] *
* *
* Description : Fournit la liste des noeuds intégrés dans une collection. *
* *
-* Retour : Enfants d'un noeud issu d'une collection Yaml. *
+* Retour : Enfants d'un noeud issu d'une collection YAML. *
* *
* Remarques : - *
* *
@@ -275,59 +295,63 @@ GYamlNode **g_yaml_collection_get_nodes(const GYamlCollection *collec, size_t *c
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* nodes = liste de noeuds avec correspondance établie. [OUT] *
-* count = quantité de ces noeuds. [OUT] *
+* Paramètres : collec = noeud d'arborescence YAML à consulter. *
* *
-* Description : Recherche les noeuds correspondant à un chemin. *
+* Description : Fournit le premier noeud intégré dans une collection. *
* *
-* Retour : - *
+* Retour : Noeud issu d'une collection YAML. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_yaml_collection_find_by_path(const GYamlCollection *collec, const char *path, bool prepare, GYamlNode ***nodes, size_t *count)
+GYamlNode *g_yaml_collection_get_first_node(const GYamlCollection *collec)
{
- size_t i; /* Boucle de parcours */
+ GYamlNode *result; /* Elément à retourner */
- if (path[0] != '/')
- goto wrong_path;
+ if (collec->count == 0)
+ result = NULL;
- if (path[1] == '\0')
+ else
{
- if (prepare)
- {
- *nodes = realloc(*nodes, ++(*count) * sizeof(GYamlNode **));
+ result = collec->nodes[0];
+ g_object_ref(G_OBJECT(result));
+ }
- g_object_ref(G_OBJECT(collec));
- (*nodes)[*count - 1] = G_YAML_NODE(collec);
+ return result;
- }
- else
- {
- *nodes = realloc(*nodes, (*count + collec->count) * sizeof(GYamlNode **));
+}
- for (i = 0; i < collec->count; i++)
- {
- g_object_ref(G_OBJECT(collec->nodes[i]));
- (*nodes)[*count + i] = collec->nodes[i];
- }
- *count += collec->count;
- }
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
- }
- else
- for (i = 0; i < collec->count; i++)
- _g_yaml_node_find_by_path(collec->nodes[i], path, prepare, nodes, count);
+/******************************************************************************
+* *
+* Paramètres : collec = noeud d'arborescence YAML à consulter. *
+* path = chemin d'accès à parcourir. *
+* *
+* Description : Recherche le premier noeud correspondant à un chemin. *
+* *
+* Retour : Noeud avec la correspondance établie ou NULL si non trouvé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlNode *g_yaml_collection_find_first_by_path(GYamlCollection *collec, const char *path)
+{
+ GYamlNode *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
- wrong_path:
+ for (i = 0; i < collec->count && result == NULL; i++)
+ result = g_yaml_node_find_first_by_path(collec->nodes[i], path);
- ;
+ return result;
}
diff --git a/plugins/yaml/collection.h b/plugins/yaml/collection.h
index 4d74d29..8a026ae 100644
--- a/plugins/yaml/collection.h
+++ b/plugins/yaml/collection.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * collection.h - prototypes pour une collection de noeuds Yaml de type "sequence" ou "mapping"
+ * collection.h - prototypes pour une collection de noeuds YAML de type "sequence" ou "mapping"
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -41,28 +41,31 @@
#define G_YAML_COLLEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_YAML_COLLEC, GYamlCollectionClass))
-/* Collection de noeuds au format Yaml (instance) */
+/* Collection de noeuds au format YAML (instance) */
typedef struct _GYamlCollection GYamlCollection;
-/* Collection de noeuds au format Yaml (classe) */
+/* Collection de noeuds au format YAML (classe) */
typedef struct _GYamlCollectionClass GYamlCollectionClass;
-/* Indique le type défini pour une collection de noeuds Yaml. */
+/* Indique le type défini pour une collection de noeuds YAML. */
GType g_yaml_collection_get_type(void);
-/* Construit une collection de noeuds Yaml. */
+/* Construit une collection de noeuds YAML. */
GYamlCollection *g_yaml_collection_new(bool);
-/* Indique la nature d'une collection Yaml. */
+/* Indique la nature d'une collection YAML. */
bool g_yaml_collection_is_sequence(const GYamlCollection *);
-/* Ajoute un noeud à une collection de noeuds Yaml. */
+/* Ajoute un noeud à une collection de noeuds YAML. */
void g_yaml_collection_add_node(GYamlCollection *, GYamlNode *);
/* Fournit la liste des noeuds intégrés dans une collection. */
GYamlNode **g_yaml_collection_get_nodes(const GYamlCollection *, size_t *);
+/* Fournit le premier noeud intégré dans une collection. */
+GYamlNode *g_yaml_collection_get_first_node(const GYamlCollection *);
+
#endif /* PLUGINS_YAML_COLLECTION_H */
diff --git a/plugins/yaml/core.c b/plugins/yaml/core.c
index ffc7edd..7dc0570 100644
--- a/plugins/yaml/core.c
+++ b/plugins/yaml/core.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* core.c - lecture de contenus au format Yaml
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -27,12 +27,12 @@
#include <plugins/self.h>
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
# define PG_REQ RL("PyChrysalide")
#else
# define PG_REQ NO_REQ
@@ -63,7 +63,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
result = true;
-#ifdef HAVE_PYTHON3_BINDINGS
+#ifdef INCLUDE_PYTHON3_BINDINGS
if (result)
result = add_yaml_module_to_python_module();
diff --git a/plugins/yaml/core.h b/plugins/yaml/core.h
index a46dbe7..b846e24 100644
--- a/plugins/yaml/core.h
+++ b/plugins/yaml/core.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* core.h - prototypes pour la lecture de contenus au format Yaml
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
diff --git a/plugins/yaml/line.h b/plugins/yaml/line.h
deleted file mode 100644
index 00f019e..0000000
--- a/plugins/yaml/line.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * line.h - prototypes pour une ligne de contenu Yaml
- *
- * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef PLUGINS_YAML_LINE_H
-#define PLUGINS_YAML_LINE_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-
-#define G_TYPE_YAML_LINE g_yaml_line_get_type()
-#define G_YAML_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_YAML_LINE, GYamlLine))
-#define G_IS_YAML_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_YAML_LINE))
-#define G_YAML_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_YAML_LINE, GYamlLineClass))
-#define G_IS_YAML_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_YAML_LINE))
-#define G_YAML_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_YAML_LINE, GYamlLineClass))
-
-
-/* Ligne de données au format Yaml (instance) */
-typedef struct _GYamlLine GYamlLine;
-
-/* Ligne de données au format Yaml (classe) */
-typedef struct _GYamlLineClass GYamlLineClass;
-
-
-/* Indique le type défini pour une ligne de données au format Yaml. */
-GType g_yaml_line_get_type(void);
-
-/* Met en place un gestionnaire pour ligne au format Yaml. */
-GYamlLine *g_yaml_line_new(const char *, size_t);
-
-/* Fournit la taille de l'indentation d'une ligne Yaml. */
-size_t g_yaml_line_count_indent(const GYamlLine *);
-
-/* Indique si la ligne représente un élément de liste. */
-bool g_yaml_line_is_list_item(const GYamlLine *);
-
-/* Fournit la charge utile associée à une ligne Yaml. */
-const char *g_yaml_line_get_payload(const GYamlLine *);
-
-/* Fournit la clef associée à une ligne Yaml si elle existe. */
-const char *g_yaml_line_get_key(const GYamlLine *);
-
-/* Fournit la valeur associée à une ligne Yaml si elle existe. */
-const char *g_yaml_line_get_value(const GYamlLine *);
-
-
-
-#define g_yaml_line_get_number(l) 0
-
-
-
-#endif /* PLUGINS_YAML_LINE_H */
diff --git a/plugins/yaml/node-int.h b/plugins/yaml/node-int.h
index a389f61..cd87950 100644
--- a/plugins/yaml/node-int.h
+++ b/plugins/yaml/node-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * node-int.h - prototypes internes pour la définition d'un noeud Yaml
+ * node-int.h - prototypes internes pour la définition d'un noeud YAML
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,32 +29,26 @@
-/* Recherche les noeuds correspondant à un chemin. */
-typedef void (* find_yaml_node_fc) (const GYamlNode *, const char *, bool, GYamlNode ***, size_t *);
+/* Recherche le premier noeud correspondant à un chemin. */
+typedef GYamlNode * (* find_first_yaml_node_fc) (GYamlNode *, const char *);
-/* Noeud d'une arborescence au format Yaml (instance) */
+/* Noeud d'une arborescence au format YAML (instance) */
struct _GYamlNode
{
GObject parent; /* A laisser en premier */
- GYamlLine *line; /* Line Yaml d'origine */
-
};
-/* Noeud d'une arborescence au format Yaml (classe) */
+/* Noeud d'une arborescence au format YAML (classe) */
struct _GYamlNodeClass
{
GObjectClass parent; /* A laisser en premier */
- find_yaml_node_fc find; /* Recherche par chemin */
+ find_first_yaml_node_fc find; /* Recherche par chemin */
};
-/* Recherche les noeuds correspondant à un chemin. */
-void _g_yaml_node_find_by_path(const GYamlNode *, const char *, bool, GYamlNode ***, size_t *);
-
-
#endif /* PLUGINS_YAML_NODE_INT_H */
diff --git a/plugins/yaml/node.c b/plugins/yaml/node.c
index 7b3413d..ff6fa7e 100644
--- a/plugins/yaml/node.c
+++ b/plugins/yaml/node.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * node.c - définition de noeud Yaml
+ * node.c - définition de noeud YAML
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,17 +24,14 @@
#include "node.h"
-#include <string.h>
-
-
#include "node-int.h"
-/* Initialise la classe des noeuds d'arborescence Yaml. */
+/* Initialise la classe des noeuds d'arborescence YAML. */
static void g_yaml_node_class_init(GYamlNodeClass *);
-/* Initialise une instance de noeud d'arborescence Yaml. */
+/* Initialise une instance de noeud d'arborescence YAML. */
static void g_yaml_node_init(GYamlNode *);
/* Supprime toutes les références externes. */
@@ -45,7 +42,7 @@ static void g_yaml_node_finalize(GYamlNode *);
-/* Indique le type défini pour un noeud d'arborescence Yaml. */
+/* Indique le type défini pour un noeud d'arborescence YAML. */
G_DEFINE_TYPE(GYamlNode, g_yaml_node, G_TYPE_OBJECT);
@@ -53,7 +50,7 @@ G_DEFINE_TYPE(GYamlNode, g_yaml_node, G_TYPE_OBJECT);
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des noeuds d'arborescence Yaml. *
+* Description : Initialise la classe des noeuds d'arborescence YAML. *
* *
* Retour : - *
* *
@@ -77,7 +74,7 @@ static void g_yaml_node_class_init(GYamlNodeClass *klass)
* *
* Paramètres : node = instance à initialiser. *
* *
-* Description : Initialise une instance de noeud d'arborescence Yaml. *
+* Description : Initialise une instance de noeud d'arborescence YAML. *
* *
* Retour : - *
* *
@@ -87,7 +84,6 @@ static void g_yaml_node_class_init(GYamlNodeClass *klass)
static void g_yaml_node_init(GYamlNode *node)
{
- node->line = NULL;
}
@@ -106,8 +102,6 @@ static void g_yaml_node_init(GYamlNode *node)
static void g_yaml_node_dispose(GYamlNode *node)
{
- g_clear_object(&node->line);
-
G_OBJECT_CLASS(g_yaml_node_parent_class)->dispose(G_OBJECT(node));
}
@@ -134,119 +128,37 @@ static void g_yaml_node_finalize(GYamlNode *node)
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
+* Paramètres : node = noeud d'arborescence YAML à consulter. *
+* path = chemin d'accès à parcourir. *
* *
-* Description : Fournit la ligne d'origine associée à un noeud. *
+* Description : Recherche le premier noeud correspondant à un chemin. *
* *
-* Retour : Ligne Yaml à l'origine du noeud. *
+* Retour : Noeud avec la correspondance établie ou NULL si non trouvé. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlLine *g_yaml_node_get_yaml_line(const GYamlNode *node)
-{
- GYamlLine *result; /* Ligne d'origine à renvoyer */
-
- result = node->line;
-
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* nodes = liste de noeuds avec correspondance établie. [OUT] *
-* count = quantité de ces noeuds. [OUT] *
-* *
-* Description : Recherche les noeuds correspondant à un chemin. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void _g_yaml_node_find_by_path(const GYamlNode *node, const char *path, bool prepare, GYamlNode ***nodes, size_t *count)
+GYamlNode *g_yaml_node_find_first_by_path(GYamlNode *node, const char *path)
{
+ GYamlNode *result; /* Trouvaille à retourner */
GYamlNodeClass *class; /* Classe de l'instance */
- class = G_YAML_NODE_GET_CLASS(node);
-
- class->find(node, path, prepare, nodes, count);
-
-}
+ while (path[0] == '/')
+ path++;
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* nodes = liste de noeuds avec correspondance établie. [OUT] *
-* count = quantité de ces noeuds. [OUT] *
-* *
-* Description : Recherche les noeuds correspondant à un chemin. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_yaml_node_find_by_path(const GYamlNode *node, const char *path, bool prepare, GYamlNode ***nodes, size_t *count)
-{
- *nodes = NULL;
- *count = 0;
-
- _g_yaml_node_find_by_path(node, path, prepare, nodes, count);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* *
-* Description : Recherche l'unique noeud correspondant à un chemin. *
-* *
-* Retour : Noeud avec correspondance établie ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GYamlNode *g_yaml_node_find_one_by_path(const GYamlNode *node, const char *path, bool prepare)
-{
- GYamlNode *result; /* Trouvaille unique à renvoyer*/
- GYamlNode **nodes; /* Liste de noeuds trouvés */
- size_t count; /* Taille de cette liste */
- size_t i; /* Boucle de parcours */
-
- g_yaml_node_find_by_path(node, path, prepare, &nodes, &count);
-
- if (count == 1)
+ if (path[0] == '\0')
{
- result = nodes[0];
+ result = node;
g_object_ref(G_OBJECT(result));
}
else
- result = NULL;
+ {
+ class = G_YAML_NODE_GET_CLASS(node);
- for (i = 0; i < count; i++)
- g_object_unref(G_OBJECT(nodes[i]));
+ result = class->find(node, path);
- if (nodes != NULL)
- free(nodes);
+ }
return result;
diff --git a/plugins/yaml/node.h b/plugins/yaml/node.h
index 8197ef5..36c8e7b 100644
--- a/plugins/yaml/node.h
+++ b/plugins/yaml/node.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* node.h - prototypes pour une définition de noeud Yaml
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,15 +26,8 @@
#include <glib-object.h>
-#include <stdbool.h>
-#include "line.h"
-
-
-/* Depuis collection.h : collection de noeuds au format Yaml (instance) */
-typedef struct _GYamlCollection GYamlCollection;
-
#define G_TYPE_YAML_NODE g_yaml_node_get_type()
#define G_YAML_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_YAML_NODE, GYamlNode))
@@ -44,24 +37,18 @@ typedef struct _GYamlCollection GYamlCollection;
#define G_YAML_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_YAML_NODE, GYamlNodeClass))
-/* Noeud d'une arborescence au format Yaml (instance) */
+/* Noeud d'une arborescence au format YAML (instance) */
typedef struct _GYamlNode GYamlNode;
-/* Noeud d'une arborescence au format Yaml (classe) */
+/* Noeud d'une arborescence au format YAML (classe) */
typedef struct _GYamlNodeClass GYamlNodeClass;
/* Indique le type défini pour un noeud d'arborescence Yaml. */
GType g_yaml_node_get_type(void);
-/* Fournit la ligne d'origine associée à un noeud. */
-GYamlLine *g_yaml_node_get_yaml_line(const GYamlNode *);
-
-/* Recherche les noeuds correspondant à un chemin. */
-void g_yaml_node_find_by_path(const GYamlNode *, const char *, bool, GYamlNode ***, size_t *);
-
-/* Recherche l'unique noeud correspondant à un chemin. */
-GYamlNode *g_yaml_node_find_one_by_path(const GYamlNode *, const char *, bool);
+/* Recherche le premier noeud correspondant à un chemin. */
+GYamlNode *g_yaml_node_find_first_by_path(GYamlNode *, const char *);
diff --git a/plugins/yaml/pair-int.h b/plugins/yaml/pair-int.h
new file mode 100644
index 0000000..88b968d
--- /dev/null
+++ b/plugins/yaml/pair-int.h
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pair-int.h - prototypes internes pour la définition d'un noeud YAML
+ *
+ * Copyright (C) 2020-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_YAML_PAIR_INT_H
+#define PLUGINS_YAML_PAIR_INT_H
+
+
+#include "pair.h"
+
+
+#include <stdbool.h>
+
+
+#include "node-int.h"
+
+
+
+/* Noeud d'une arborescence au format YAML (instance) */
+struct _GYamlPair
+{
+ GYamlNode parent; /* A laisser en premier */
+
+ char *key; /* Clef présente dans le noeud */
+ YamlOriginalStyle key_style; /* Forme d'origine associé */
+
+ char *value; /* Valeur associée */
+ YamlOriginalStyle value_style; /* Forme d'origine associé */
+
+ GYamlCollection *children; /* Collection de noeuds */
+
+};
+
+/* Noeud d'une arborescence au format YAML (classe) */
+struct _GYamlPairClass
+{
+ GYamlNodeClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une pair clef/valeur YAML. */
+bool g_yaml_pair_create(GYamlPair *, const char *, YamlOriginalStyle, const char *, YamlOriginalStyle);
+
+
+
+#endif /* PLUGINS_YAML_PAIR_INT_H */
diff --git a/plugins/yaml/pair.c b/plugins/yaml/pair.c
index 0e96937..4faba88 100644
--- a/plugins/yaml/pair.c
+++ b/plugins/yaml/pair.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * pair.c - noeud Yaml de paire clef/valeur
+ * pair.c - noeud YAML de paire clef/valeur
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,38 +24,25 @@
#include "pair.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
-#include "node-int.h"
+#include <common/extstr.h>
+#include "pair-int.h"
-/* Noeud d'une arborescence au format Yaml (instance) */
-struct _GYamlPair
-{
- GYamlNode parent; /* A laisser en premier */
-
- char *key; /* Clef présente dans le noeud */
- char *value; /* Valeur associée */
-
- GYamlCollection *collection; /* Collection de noeuds */
-};
-
-/* Noeud d'une arborescence au format Yaml (classe) */
-struct _GYamlPairClass
-{
- GYamlNodeClass parent; /* A laisser en premier */
-};
+/* -------------------- DEFINITIONS PROPRES POUR LE SUPPORT YAML -------------------- */
-/* Initialise la classe des noeuds d'arborescence Yaml. */
+/* Initialise la classe des noeuds d'arborescence YAML. */
static void g_yaml_pair_class_init(GYamlPairClass *);
-/* Initialise une instance de noeud d'arborescence Yaml. */
+/* Initialise une instance de noeud d'arborescence YAML. */
static void g_yaml_pair_init(GYamlPair *);
/* Supprime toutes les références externes. */
@@ -64,12 +51,22 @@ static void g_yaml_pair_dispose(GYamlPair *);
/* Procède à la libération totale de la mémoire. */
static void g_yaml_pair_finalize(GYamlPair *);
-/* Recherche les noeuds correspondant à un chemin. */
-static void g_yaml_pair_find_by_path(const GYamlPair *, const char *, bool, GYamlNode ***, size_t *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Recherche le premier noeud correspondant à un chemin. */
+static GYamlNode *g_yaml_pair_find_first_by_path(GYamlPair *, const char *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITIONS PROPRES POUR LE SUPPORT YAML */
+/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour un noeud d'arborescence Yaml. */
+
+/* Indique le type défini pour un noeud d'arborescence YAML. */
G_DEFINE_TYPE(GYamlPair, g_yaml_pair, G_TYPE_YAML_NODE);
@@ -77,7 +74,7 @@ G_DEFINE_TYPE(GYamlPair, g_yaml_pair, G_TYPE_YAML_NODE);
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des noeuds d'arborescence Yaml. *
+* Description : Initialise la classe des noeuds d'arborescence YAML. *
* *
* Retour : - *
* *
@@ -97,16 +94,16 @@ static void g_yaml_pair_class_init(GYamlPairClass *klass)
node = G_YAML_NODE_CLASS(klass);
- node->find = (find_yaml_node_fc)g_yaml_pair_find_by_path;
+ node->find = (find_first_yaml_node_fc)g_yaml_pair_find_first_by_path;
}
/******************************************************************************
* *
-* Paramètres : node = instance à initialiser. *
+* Paramètres : pair = instance à initialiser. *
* *
-* Description : Initialise une instance de noeud d'arborescence Yaml. *
+* Description : Initialise une instance de noeud d'arborescence YAML. *
* *
* Retour : - *
* *
@@ -114,19 +111,22 @@ static void g_yaml_pair_class_init(GYamlPairClass *klass)
* *
******************************************************************************/
-static void g_yaml_pair_init(GYamlPair *node)
+static void g_yaml_pair_init(GYamlPair *pair)
{
- node->key = NULL;
- node->value = NULL;
+ pair->key = NULL;
+ pair->key_style = YOS_PLAIN;
+
+ pair->value = NULL;
+ pair->value_style = YOS_PLAIN;
- node->collection = NULL;
+ pair->children = NULL;
}
/******************************************************************************
* *
-* Paramètres : node = instance d'objet GLib à traiter. *
+* Paramètres : pair = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -136,18 +136,18 @@ static void g_yaml_pair_init(GYamlPair *node)
* *
******************************************************************************/
-static void g_yaml_pair_dispose(GYamlPair *node)
+static void g_yaml_pair_dispose(GYamlPair *pair)
{
- g_clear_object(&node->collection);
+ g_clear_object(&pair->children);
- G_OBJECT_CLASS(g_yaml_pair_parent_class)->dispose(G_OBJECT(node));
+ G_OBJECT_CLASS(g_yaml_pair_parent_class)->dispose(G_OBJECT(pair));
}
/******************************************************************************
* *
-* Paramètres : node = instance d'objet GLib à traiter. *
+* Paramètres : pair = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -157,24 +157,27 @@ static void g_yaml_pair_dispose(GYamlPair *node)
* *
******************************************************************************/
-static void g_yaml_pair_finalize(GYamlPair *node)
+static void g_yaml_pair_finalize(GYamlPair *pair)
{
- if (node->key != NULL)
- free(node->key);
+ if (pair->key != NULL)
+ free(pair->key);
- if (node->value != NULL)
- free(node->value);
+ if (pair->value != NULL)
+ free(pair->value);
- G_OBJECT_CLASS(g_yaml_pair_parent_class)->finalize(G_OBJECT(node));
+ G_OBJECT_CLASS(g_yaml_pair_parent_class)->finalize(G_OBJECT(pair));
}
/******************************************************************************
* *
-* Paramètres : line = ligne Yaml à l'origine du futur noeud. *
+* Paramètres : key = désignation pour le noeud YAML. *
+* kstyle = format d'origine de la clef. *
+* value = éventuelle valeur directe portée par le noeud. *
+* vstyle = éventuel format d'origine de l'éventuelle valeur. *
* *
-* Description : Construit un noeud d'arborescence Yaml. *
+* Description : Construit un noeud d'arborescence YAML. *
* *
* Retour : Instance mise en place ou NULL en cas d'échec. *
* *
@@ -182,33 +185,14 @@ static void g_yaml_pair_finalize(GYamlPair *node)
* *
******************************************************************************/
-GYamlPair *g_yaml_pair_new(GYamlLine *line)
+GYamlPair *g_yaml_pair_new(const char *key, YamlOriginalStyle kstyle, const char *value, YamlOriginalStyle vstyle)
{
GYamlPair *result; /* Structure à retourner */
- const char *key; /* Clef associée au noeud */
- const char *value; /* Eventuelle valeur associée */
-
- key = g_yaml_line_get_key(line);
- value = g_yaml_line_get_value(line);
-
- if (key == NULL)
- result = NULL;
- else
- {
- result = g_object_new(G_TYPE_YAML_PAIR, NULL);
-
- G_YAML_NODE(result)->line = line;
- g_object_ref(G_OBJECT(line));
+ result = g_object_new(G_TYPE_YAML_PAIR, NULL);
- result->key = strdup(key);
-
- if (value == NULL)
- result->value = NULL;
- else
- result->value = strdup(value);
-
- }
+ if (!g_yaml_pair_create(result, key, kstyle, value, vstyle))
+ g_clear_object(&result);
return result;
@@ -217,105 +201,126 @@ GYamlPair *g_yaml_pair_new(GYamlLine *line)
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* nodes = liste de noeuds avec correspondance établie. [OUT] *
-* count = quantité de ces noeuds. [OUT] *
+* Paramètres : pair = paire YAML à initialiser pleinement. *
+* key = désignation pour le noeud YAML. *
+* kstyle = format d'origine de la clef. *
+* value = éventuelle valeur directe portée par le noeud. *
+* vstyle = éventuel format d'origine de l'éventuelle valeur. *
* *
-* Description : Recherche les noeuds correspondant à un chemin. *
+* Description : Met en place une pair clef/valeur YAML. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_yaml_pair_find_by_path(const GYamlPair *node, const char *path, bool prepare, GYamlNode ***nodes, size_t *count)
+bool g_yaml_pair_create(GYamlPair *pair, const char *key, YamlOriginalStyle kstyle, const char *value, YamlOriginalStyle vstyle)
{
- char *next; /* Prochaine partie du chemin */
- size_t cmplen; /* Etendue de la comparaison */
- int ret; /* Bilan d'une comparaison */
+ bool result; /* Bilan à retourner */
- if (path[0] == '\0')
- goto exit;
+ result = true;
- /* Correspondance au niveau du noeud ? */
+ pair->key = strdup(key);
+ pair->key_style = kstyle;
- if (path[0] == '/')
+ if (value != NULL)
{
- path++;
+ pair->value = strdup(value);
+ pair->value_style = vstyle;
+ }
- if (path[0] == '\0')
- goto matched;
+ return result;
- }
+}
- next = strchr(path, '/');
- if (next == NULL)
- ret = strcmp(path, node->key);
+/******************************************************************************
+* *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
+* *
+* Description : Fournit la clef représentée dans une paire en YAML. *
+* *
+* Retour : Clef sous forme de chaîne de caractères. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- else
- {
- cmplen = next - path;
+const char *g_yaml_pair_get_key(const GYamlPair *pair)
+{
+ char *result; /* Valeur à retourner */
- if (cmplen == 0)
- goto cont;
+ result = pair->key;
- ret = strncmp(path, node->key, cmplen);
+ return result;
- }
+}
- if (ret != 0)
- goto done;
- else if (next != NULL)
- {
- path += cmplen;
- goto cont;
- }
+/******************************************************************************
+* *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
+* *
+* Description : Indique le format d'origine YAML associé à la clef. *
+* *
+* Retour : Valeur renseignée lors du chargement du noeud. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- matched:
+YamlOriginalStyle g_yaml_pair_get_key_style(const GYamlPair *pair)
+{
+ YamlOriginalStyle result; /* Indication à retourner */
- *nodes = realloc(*nodes, ++(*count) * sizeof(GYamlNode **));
+ result = pair->key_style;
- g_object_ref(G_OBJECT(node));
- (*nodes)[*count - 1] = G_YAML_NODE(node);
+ return result;
- goto done;
+}
- cont:
- if (node->collection != NULL)
- _g_yaml_node_find_by_path(G_YAML_NODE(node->collection), path, prepare, nodes, count);
+/******************************************************************************
+* *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
+* *
+* Description : Fournit l'éventuelle valeur d'une paire en YAML. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- done:
+const char *g_yaml_pair_get_value(const GYamlPair *pair)
+{
+ char *result; /* Valeur à retourner */
- exit:
+ result = pair->value;
- ;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
* *
-* Description : Fournit la clef représentée dans une paire en Yaml. *
+* Description : Indique le format d'origine YAML associé à la valeur. *
* *
-* Retour : Clef sous forme de chaîne de caractères. *
+* Retour : Valeur renseignée lors du chargement du noeud. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_yaml_pair_get_key(const GYamlPair *node)
+YamlOriginalStyle g_yaml_pair_get_value_style(const GYamlPair *pair)
{
- char *result; /* Valeur à retourner */
+ YamlOriginalStyle result; /* Indication à retourner */
- result = node->key;
+ result = pair->value_style;
return result;
@@ -324,9 +329,9 @@ const char *g_yaml_pair_get_key(const GYamlPair *node)
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
* *
-* Description : Fournit l'éventuelle valeur d'une paire en Yaml. *
+* Description : Rassemble une éventuelle séquence de valeurs attachées. *
* *
* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
* *
@@ -334,11 +339,88 @@ const char *g_yaml_pair_get_key(const GYamlPair *node)
* *
******************************************************************************/
-const char *g_yaml_pair_get_value(const GYamlPair *node)
+char *g_yaml_pair_aggregate_value(const GYamlPair *pair)
{
char *result; /* Valeur à retourner */
+ GYamlNode **nodes; /* Eventuels noeuds trouvés */
+ size_t count; /* Quantité de ces noeuds */
+ size_t i; /* Boucle de parcours */
+ GYamlPair *child; /* Couple clef/valeur enfant */
+ bool failed; /* Détection d'un échec */
+
+ result = NULL;
+
+ if (pair->value != NULL)
+ result = strdup(pair->value);
+
+ else if (pair->children != NULL)
+ {
+ if (!g_yaml_collection_is_sequence(pair->children))
+ goto exit;
+
+ nodes = g_yaml_collection_get_nodes(pair->children, &count);
+
+ if (count == 0)
+ result = strdup("[ ]");
+
+ else
+ {
+ result = strdup("[ ");
+
+ for (i = 0; i < count; i++)
+ {
+ if (!G_IS_YAML_PAIR(nodes[i]))
+ break;
+
+ child = G_YAML_PAIR(nodes[i]);
+
+ if (child->value != NULL)
+ break;
+
+ if (i > 0)
+ result = stradd(result, ", ");
+
+ switch (child->key_style)
+ {
+ case YOS_PLAIN:
+ result = stradd(result, child->key);
+ break;
+
+ case YOS_SINGLE_QUOTED:
+ result = straddfmt(result, "'%s'", child->key);
+ break;
+
+ case YOS_DOUBLE_QUOTED:
+ result = straddfmt(result, "\"%s\"", child->key);
+ break;
+
+ }
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
- result = node->value;
+ failed = (i < count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ free(nodes);
+
+ if (failed)
+ {
+ free(result);
+ result = NULL;
+ }
+
+ else
+ result = stradd(result, " ]");
+
+ }
+
+ }
+
+ exit:
return result;
@@ -347,10 +429,10 @@ const char *g_yaml_pair_get_value(const GYamlPair *node)
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à compléter. *
-* collec = collection de noeuds Yaml. *
+* Paramètres : pair = noeud d'arborescence YAML à compléter. *
+* children = collection de noeuds YAML. *
* *
-* Description : Attache une collection de noeuds Yaml à un noeud. *
+* Description : Attache une collection de noeuds YAML à un noeud. *
* *
* Retour : - *
* *
@@ -358,33 +440,33 @@ const char *g_yaml_pair_get_value(const GYamlPair *node)
* *
******************************************************************************/
-void g_yaml_pair_set_collection(GYamlPair *node, GYamlCollection *collec)
+void g_yaml_pair_set_children(GYamlPair *pair, GYamlCollection *children)
{
- g_clear_object(&node->collection);
+ g_clear_object(&pair->children);
- g_object_ref_sink(G_OBJECT(collec));
- node->collection = collec;
+ g_object_ref_sink(G_OBJECT(children));
+ pair->children = children;
}
/******************************************************************************
* *
-* Paramètres : node = noeud d'arborescence Yaml à consulter. *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
* *
* Description : Fournit une éventuelle collection rattachée à un noeud. *
* *
-* Retour : Collection de noeuds Yaml ou NULL. *
+* Retour : Collection de noeuds YAML ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-GYamlCollection *g_yaml_pair_get_collection(const GYamlPair *node)
+GYamlCollection *g_yaml_pair_get_children(const GYamlPair *pair)
{
GYamlCollection *result; /* Collection à renvoyer */
- result = node->collection;
+ result = pair->children;
if (result != NULL)
g_object_ref(G_OBJECT(result));
@@ -392,3 +474,76 @@ GYamlCollection *g_yaml_pair_get_collection(const GYamlPair *node)
return result;
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : pair = noeud d'arborescence YAML à consulter. *
+* path = chemin d'accès à parcourir. *
+* *
+* Description : Recherche le premier noeud correspondant à un chemin. *
+* *
+* Retour : Noeud avec la correspondance établie ou NULL si non trouvé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlNode *g_yaml_pair_find_first_by_path(GYamlPair *pair, const char *path)
+{
+ GYamlNode *result; /* Trouvaille à retourner */
+ char *next; /* Prochaine partie du chemin */
+ size_t cmplen; /* Etendue de la comparaison */
+ int ret; /* Bilan d'une comparaison */
+
+ assert(path[0] != '/' && path[0] != '\0');
+
+ /* Correspondance au niveau du noeud ? */
+
+ next = strchr(path, '/');
+
+ if (next == NULL)
+ ret = strcmp(path, pair->key);
+
+ else
+ {
+ cmplen = next - path;
+ assert(cmplen > 0);
+
+ ret = strncmp(path, pair->key, cmplen);
+
+ }
+
+ /* Si correspondance il y a... */
+
+ if (ret == 0)
+ {
+ /* ... et que la recherche se trouve en bout de parcours */
+ if (next == NULL)
+ {
+ result = G_YAML_NODE(pair);
+ g_object_ref(G_OBJECT(result));
+ }
+
+ /* Recherche supplémentaire dans les sous-noeuds ? */
+
+ else if (pair->children != NULL)
+ result = g_yaml_node_find_first_by_path(G_YAML_NODE(pair->children), path + cmplen);
+
+ else
+ result = NULL;
+
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
diff --git a/plugins/yaml/pair.h b/plugins/yaml/pair.h
index 986fef7..5265392 100644
--- a/plugins/yaml/pair.h
+++ b/plugins/yaml/pair.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* pair.h - prototypes pour un noeud Yaml de paire clef/valeur
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -30,7 +30,6 @@
#include "collection.h"
-#include "line.h"
#include "node.h"
@@ -49,23 +48,42 @@ typedef struct _GYamlPair GYamlPair;
typedef struct _GYamlPairClass GYamlPairClass;
+/* Format d'origine des éléments du couple clef/valeur */
+typedef enum _YamlOriginalStyle
+{
+ YOS_PLAIN, /* Mode brut, par défaut */
+ YOS_SINGLE_QUOTED, /* Encadré simplement */
+ YOS_DOUBLE_QUOTED, /* ENcadré avec des guillemets */
+
+} YamlOriginalStyle;
+
+
/* Indique le type défini pour un noeud d'arborescence Yaml. */
GType g_yaml_pair_get_type(void);
/* Construit un noeud d'arborescence Yaml. */
-GYamlPair *g_yaml_pair_new(GYamlLine *);
+GYamlPair *g_yaml_pair_new(const char *, YamlOriginalStyle, const char *, YamlOriginalStyle);
/* Fournit la clef représentée dans une paire en Yaml. */
const char *g_yaml_pair_get_key(const GYamlPair *);
+/* Indique le format d'origine YAML associé à la clef. */
+YamlOriginalStyle g_yaml_pair_get_key_style(const GYamlPair *);
+
/* Fournit l'éventuelle valeur d'une paire en Yaml. */
const char *g_yaml_pair_get_value(const GYamlPair *);
+/* Indique le format d'origine YAML associé à la valeur. */
+YamlOriginalStyle g_yaml_pair_get_value_style(const GYamlPair *);
+
+/* Rassemble une éventuelle séquence de valeurs attachées. */
+char *g_yaml_pair_aggregate_value(const GYamlPair *);
+
/* Attache une collection de noeuds Yaml à un noeud. */
-void g_yaml_pair_set_collection(GYamlPair *, GYamlCollection *);
+void g_yaml_pair_set_children(GYamlPair *, GYamlCollection *);
/* Fournit une éventuelle collection rattachée à un noeud. */
-GYamlCollection *g_yaml_pair_get_collection(const GYamlPair *);
+GYamlCollection *g_yaml_pair_get_children(const GYamlPair *);
diff --git a/plugins/yaml/parser.c b/plugins/yaml/parser.c
new file mode 100644
index 0000000..8c06723
--- /dev/null
+++ b/plugins/yaml/parser.c
@@ -0,0 +1,299 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - lecteur de contenu Yaml
+ *
+ * Copyright (C) 2019-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 "parser.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <yaml.h>
+#include <gio/gio.h>
+
+
+#include <analysis/contents/file.h>
+
+
+#include "collection.h"
+#include "pair.h"
+
+
+#define SCALAR_STYLE_TO_ORIGINAL_STYLE(v) \
+ ({ \
+ YamlOriginalStyle __result; \
+ if (v == YAML_SINGLE_QUOTED_SCALAR_STYLE) \
+ __result = YOS_SINGLE_QUOTED; \
+ else if (v == YAML_DOUBLE_QUOTED_SCALAR_STYLE) \
+ __result = YOS_DOUBLE_QUOTED; \
+ else \
+ __result = YOS_PLAIN; \
+ __result; \
+ })
+
+
+/* Construit la version GLib d'un noeud YAML brut. */
+static GYamlPair *build_pair_from_yaml(yaml_document_t *, int, int);
+
+/* Transforme un noeud YAML brut en sa version Glib. */
+static GYamlNode *translate_yaml_node(yaml_document_t *, yaml_node_t *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : document = gestionnaire de l'ensemble des noeuds bruts. *
+* key = indice de la clef du noeud à convertir. *
+* value = indice de la valeur du noeud à convertir. *
+* *
+* Description : Construit la version GLib d'un noeud YAML brut. *
+* *
+* Retour : Noeud GLib obtenu ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlPair *build_pair_from_yaml(yaml_document_t *document, int key, int value)
+{
+ GYamlPair *result; /* Racine à retourner */
+ yaml_node_t *key_node; /* Noeud brut de la clef */
+ yaml_node_t *value_node; /* Noeud brut de la valeur */
+ GYamlNode *children; /* Collection de noeuds YAML */
+
+ result = NULL;
+
+ key_node = yaml_document_get_node(document, key);
+ assert(key_node != NULL);
+
+ if (key_node->type != YAML_SCALAR_NODE)
+ goto exit;
+
+ value_node = yaml_document_get_node(document, value);
+ assert(value_node != NULL);
+
+ if (value_node->type == YAML_SCALAR_NODE)
+ result = g_yaml_pair_new((char *)key_node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(key_node->data.scalar.style),
+ (char *)value_node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(value_node->data.scalar.style));
+
+ else
+ {
+ children = translate_yaml_node(document, value_node);
+
+ if (children != NULL)
+ {
+ result = g_yaml_pair_new((char *)key_node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(key_node->data.scalar.style),
+ NULL, YOS_PLAIN);
+
+ g_yaml_pair_set_children(result, G_YAML_COLLEC(children));
+
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : document = gestionnaire de l'ensemble des noeuds bruts. *
+* node = point de départ des transformations. *
+* *
+* Description : Transforme un noeud YAML brut en sa version Glib. *
+* *
+* Retour : Noeud GLib obtenu ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlNode *translate_yaml_node(yaml_document_t *document, yaml_node_t *node)
+{
+ GYamlNode *result; /* Racine à retourner */
+ yaml_node_item_t *index; /* Elément d'une série */
+ yaml_node_t *item; /* Elément d'une série */
+ GYamlNode *child; /* Version GLib de l'élément */
+ yaml_node_pair_t *pair; /* Combinaison clef/valeur */
+ GYamlPair *sub; /* Sous-noeud à intégrer */
+
+ switch (node->type)
+ {
+ case YAML_SCALAR_NODE:
+ result = G_YAML_NODE(g_yaml_pair_new((char *)node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(node->data.scalar.style),
+ NULL, YOS_PLAIN));
+ break;
+
+ case YAML_SEQUENCE_NODE:
+
+ result = G_YAML_NODE(g_yaml_collection_new(true));
+
+ for (index = node->data.sequence.items.start; index < node->data.sequence.items.top; index++)
+ {
+ item = yaml_document_get_node(document, *index);
+ assert(item != NULL);
+
+ child = translate_yaml_node(document, item);
+
+ if (child == NULL)
+ {
+ g_clear_object(&result);
+ break;
+ }
+
+ g_yaml_collection_add_node(G_YAML_COLLEC(result), child);
+
+ }
+
+ break;
+
+ case YAML_MAPPING_NODE:
+
+ result = G_YAML_NODE(g_yaml_collection_new(false));
+
+ for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++)
+ {
+ sub = build_pair_from_yaml(document, pair->key, pair->value);
+
+ if (sub == NULL)
+ {
+ g_clear_object(&result);
+ break;
+ }
+
+ g_yaml_collection_add_node(G_YAML_COLLEC(result), G_YAML_NODE(sub));
+
+ }
+
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : text = définitions textuelles d'un contenu brut. *
+* len = taille de ces définitions. *
+* *
+* Description : Crée une arborescence YAML pour contenu au format adapté. *
+* *
+* Retour : Arborescence YAML mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlNode *parse_yaml_from_text(const char *text, size_t len)
+{
+ GYamlNode *result; /* Racine à retourner */
+ yaml_parser_t parser; /* Lecteur du contenu fourni */
+ yaml_document_t document; /* Document YAML constitué */
+ int ret; /* Bilan de la constitution */
+ yaml_node_t *root; /* Elément racine brut */
+
+ result = NULL;
+
+ yaml_parser_initialize(&parser);
+
+ yaml_parser_set_input_string(&parser, (const unsigned char *)text, len);
+
+ ret = yaml_parser_load(&parser, &document);
+ if (ret != 1) goto bad_loading;
+
+ root = yaml_document_get_root_node(&document);
+
+ if (root != NULL)
+ result = translate_yaml_node(&document, root);
+
+ yaml_document_delete(&document);
+
+ bad_loading:
+
+ yaml_parser_delete(&parser);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = chemin vers des définitions de règles. *
+* *
+* Description : Crée une arborescence YAML pour fichier au format adapté. *
+* *
+* Retour : Arborescence YAML mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlNode *parse_yaml_from_file(const char *filename)
+{
+ GYamlNode *result; /* Racine à retourner */
+ GBinContent *content; /* Fichier à parcourir */
+ phys_t size; /* Taille du contenu associé */
+ vmpa2t start; /* Tête de lecture */
+ const bin_t *data; /* Données à consulter */
+ char *dumped; /* Contenu manipulable */
+
+ result = NULL;
+
+ content = g_file_content_new(filename);
+ if (content == NULL) goto no_content;
+
+ size = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &start);
+ data = g_binary_content_get_raw_access(content, &start, size);
+
+ dumped = malloc((size + 1) * sizeof(char));
+
+ memcpy(dumped, data, size);
+ dumped[size] = '\0';
+
+ result = parse_yaml_from_text(dumped, size);
+
+ free(dumped);
+
+ g_object_unref(G_OBJECT(content));
+
+ no_content:
+
+ return result;
+
+}
diff --git a/plugins/yaml/parser.h b/plugins/yaml/parser.h
new file mode 100644
index 0000000..761e12b
--- /dev/null
+++ b/plugins/yaml/parser.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - prototypes pour le lecteur de contenu Yaml
+ *
+ * Copyright (C) 2019-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_YAML_PARSER_H
+#define PLUGINS_YAML_PARSER_H
+
+
+#include <sys/types.h>
+
+
+#include "node.h"
+
+
+
+/* Crée une arborescence YAML pour contenu au format adapté. */
+GYamlNode *parse_yaml_from_text(const char *, size_t);
+
+/* Crée une arborescence YAML pour fichier au format adapté. */
+GYamlNode *parse_yaml_from_file(const char *);
+
+
+
+#endif /* PLUGINS_YAML_PARSER_H */
diff --git a/plugins/yaml/python/Makefile.am b/plugins/yaml/python/Makefile.am
index 4662a8e..f3dc989 100644
--- a/plugins/yaml/python/Makefile.am
+++ b/plugins/yaml/python/Makefile.am
@@ -3,23 +3,16 @@ noinst_LTLIBRARIES = libyamlpython.la
libyamlpython_la_SOURCES = \
collection.h collection.c \
- line.h line.c \
+ constants.h constants.c \
module.h module.c \
node.h node.c \
pair.h pair.c \
- reader.h reader.c \
- scalar.h scalar.c \
- tree.h tree.c
+ parser.h parser.c
-libyamlpython_la_LDFLAGS =
+libyamlpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libyamlpython_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
- -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/yaml/python/collection.c b/plugins/yaml/python/collection.c
index e21bb9e..fd8e08a 100644
--- a/plugins/yaml/python/collection.c
+++ b/plugins/yaml/python/collection.c
@@ -28,18 +28,22 @@
#include <pygobject.h>
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
#include <plugins/pychrysalide/helpers.h>
#include "node.h"
-#include "../collection.h"
+#include "../collection-int.h"
-/* Crée un nouvel objet Python de type 'YamlCollection'. */
-static PyObject *py_yaml_collection_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(yaml_collection, G_TYPE_YAML_COLLEC);
-/* Indique la nature d'une collection Yaml. */
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_yaml_collection_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique la nature d'une collection YAML. */
static PyObject *py_yaml_collection_is_sequence(PyObject *, void *);
/* Fournit la liste des noeuds intégrés dans une collection. */
@@ -49,44 +53,56 @@ static PyObject *py_yaml_collection_get_nodes(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'YamlCollection'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_collection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_yaml_collection_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
int seq; /* Indicateur de type */
int ret; /* Bilan de lecture des args. */
GYamlCollection *collec; /* Création GLib à transmettre */
#define YAML_COLLECTION_DOC \
- "YamlCollection handles a collection of Yaml nodes.\n" \
+ "YamlCollection handles a collection of YAML nodes.\n" \
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
" YamlCollection(seq=False)\n" \
"\n" \
- "Where seq defines if the collection will be a sequence or a mapping of nodes."
+ "Where *seq* is a boolean value which defines if the collection will be a" \
+ " sequence or a mapping of nodes."
+
+ /* Récupération des paramètres */
ret = PyArg_ParseTuple(args, "p", &seq);
- if (!ret) return NULL;
+ if (!ret) return -1;
- collec = g_yaml_collection_new(seq);
+ /* Initialisation d'un objet GLib */
- g_object_ref_sink(G_OBJECT(collec));
- result = pygobject_new(G_OBJECT(collec));
- g_object_unref(collec);
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
- return result;
+ /* Eléments de base */
+
+ collec = G_YAML_COLLEC(pygobject_get(self));
+
+ if (!g_yaml_collection_create(collec, seq))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create YAML collection."));
+ return -1;
+
+ }
+
+ return 0;
}
@@ -98,7 +114,7 @@ static PyObject *py_yaml_collection_new(PyTypeObject *type, PyObject *args, PyOb
* *
* Description : Fournit la liste des noeuds intégrés dans une collection. *
* *
-* Retour : Enfants d'un noeud issu d'une collection Yaml. *
+* Retour : Enfants d'un noeud issu d'une collection YAML. *
* *
* Remarques : - *
* *
@@ -152,7 +168,7 @@ static PyObject *py_yaml_collection_get_nodes(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Indique la nature d'une collection Yaml. *
+* Description : Indique la nature d'une collection YAML. *
* *
* Retour : Nature de la collection. *
* *
@@ -169,7 +185,7 @@ static PyObject *py_yaml_collection_is_sequence(PyObject *self, void *closure)
#define YAML_COLLECTION_IS_SEQUENCE_ATTRIB PYTHON_IS_DEF_FULL \
( \
sequence, py_yaml_collection, \
- "Nature of the collection: True is the collection is a sequence," \
+ "Nature of the collection: True if the collection is a sequence," \
" False if it is a mapping of \"key: value\" nodes." \
)
@@ -222,7 +238,9 @@ PyTypeObject *get_python_yaml_collection_type(void)
.tp_methods = py_yaml_collection_methods,
.tp_getset = py_yaml_collection_getseters,
- .tp_new = py_yaml_collection_new
+
+ .tp_init = py_yaml_collection_init,
+ .tp_new = py_yaml_collection_new,
};
@@ -233,7 +251,7 @@ PyTypeObject *get_python_yaml_collection_type(void)
/******************************************************************************
* *
-* Paramètres : module = module dont la définition est à compléter. *
+* Paramètres : - *
* *
* Description : Prend en charge l'objet 'pychrysalide.....YamlCollection. *
* *
@@ -243,17 +261,24 @@ PyTypeObject *get_python_yaml_collection_type(void)
* *
******************************************************************************/
-bool register_python_yaml_collection(PyObject *module)
+bool ensure_python_yaml_collection_is_registered(void)
{
PyTypeObject *type; /* Type Python 'YamlCollection'*/
+ PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
type = get_python_yaml_collection_type();
- dict = PyModule_GetDict(module);
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.yaml");
+
+ dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_COLLEC, type, get_python_yaml_node_type()))
- return false;
+ if (!register_class_for_pygobject(dict, G_TYPE_YAML_COLLEC, type))
+ return false;
+
+ }
return true;
@@ -265,7 +290,7 @@ bool register_python_yaml_collection(PyObject *module)
* 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 collection de noeuds de format Yaml. *
+* Description : Tente de convertir en collection de noeuds de format YAML. *
* *
* Retour : Bilan de l'opération, voire indications supplémentaires. *
* *
@@ -287,7 +312,7 @@ int convert_to_yaml_collection(PyObject *arg, void *dst)
break;
case 0:
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Yaml collection");
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to YAML collection");
break;
case 1:
diff --git a/plugins/yaml/python/collection.h b/plugins/yaml/python/collection.h
index ab2caba..24875d0 100644
--- a/plugins/yaml/python/collection.h
+++ b/plugins/yaml/python/collection.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* collection.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/collection.h"
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -35,9 +35,9 @@
PyTypeObject *get_python_yaml_collection_type(void);
/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlCollection'. */
-bool register_python_yaml_collection(PyObject *);
+bool ensure_python_yaml_collection_is_registered(void);
-/* Tente de convertir en collection de noeuds de format Yaml. */
+/* Tente de convertir en collection de noeuds de format YAML. */
int convert_to_yaml_collection(PyObject *, void *);
diff --git a/plugins/yaml/python/constants.c b/plugins/yaml/python/constants.c
new file mode 100644
index 0000000..ff04584
--- /dev/null
+++ b/plugins/yaml/python/constants.c
@@ -0,0 +1,127 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - prise en charge des constantes liées à YAML
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "constants.h"
+
+
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../pair.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives au noeuds principaux. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_yaml_pair_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "PLAIN", YOS_PLAIN);
+ if (result) result = add_const_to_group(values, "SINGLE_QUOTED", YOS_SINGLE_QUOTED);
+ if (result) result = add_const_to_group(values, "DOUBLE_QUOTED", YOS_DOUBLE_QUOTED);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "YamlOriginalStyle", values,
+ "Original style of scalar YAML nodes.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 constante YamlOriginalStyle. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_yaml_pair_original_style(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 YamlOriginalStyle");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > YOS_DOUBLE_QUOTED)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for YamlOriginalStyle");
+ result = 0;
+ }
+
+ else
+ *((YamlOriginalStyle *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/yaml/python/constants.h b/plugins/yaml/python/constants.h
new file mode 100644
index 0000000..d31bb69
--- /dev/null
+++ b/plugins/yaml/python/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour la prise en charge des constantes liées à YAML
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_YAML_PYTHON_CONSTANTS_H
+#define _PLUGINS_YAML_PYTHON_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives au noeuds principaux. */
+bool define_yaml_pair_constants(PyTypeObject *);
+
+/* Tente de convertir en constante YamlOriginalStyle. */
+int convert_to_yaml_pair_original_style(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_YAML_PYTHON_CONSTANTS_H */
diff --git a/plugins/yaml/python/module.c b/plugins/yaml/python/module.c
index 90823e8..3d6a4e8 100644
--- a/plugins/yaml/python/module.c
+++ b/plugins/yaml/python/module.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* module.c - intégration du répertoire yaml en tant que module
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,12 +34,9 @@
#include "collection.h"
-#include "line.h"
#include "node.h"
#include "pair.h"
-#include "reader.h"
-#include "scalar.h"
-#include "tree.h"
+#include "parser.h"
@@ -62,7 +59,12 @@ bool add_yaml_module_to_python_module(void)
PyObject *module; /* Sous-module mis en place */
#define PYCHRYSALIDE_PLUGINS_YAML_DOC \
- "yaml is a module providing access to Yaml content."
+ "yaml is a module providing access to YAML content.\n" \
+ "\n" \
+ "The parsing is provided by an external library: " \
+ " https://github.com/yaml/libyaml . The Python module only" \
+ " creates some glue to access YAML content from GObject" \
+ " code."
static PyModuleDef py_chrysalide_yaml_module = {
@@ -105,19 +107,12 @@ bool add_yaml_module_to_python_module(void)
bool populate_yaml_module(void)
{
bool result; /* Bilan à retourner */
- PyObject *module; /* Module à recompléter */
- result = true;
+ result = populate_yaml_module_with_parsers();
- module = get_access_to_python_module("pychrysalide.plugins.yaml");
-
- if (result) result = register_python_yaml_node(module);
- if (result) result = register_python_yaml_collection(module);
- if (result) result = register_python_yaml_line(module);
- if (result) result = register_python_yaml_pair(module);
- if (result) result = register_python_yaml_reader(module);
- if (result) result = register_python_yaml_scalar(module);
- if (result) result = register_python_yaml_tree(module);
+ if (result) result = ensure_python_yaml_node_is_registered();
+ if (result) result = ensure_python_yaml_collection_is_registered();
+ if (result) result = ensure_python_yaml_pair_is_registered();
assert(result);
diff --git a/plugins/yaml/python/node.c b/plugins/yaml/python/node.c
index 7db6e59..7d2fef0 100644
--- a/plugins/yaml/python/node.c
+++ b/plugins/yaml/python/node.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* node.c - équivalent Python du fichier "plugins/yaml/node.c"
*
- * Copyright (C) 2019-2020 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,101 +28,55 @@
#include <pygobject.h>
+#include <plugins/pychrysalide/access.h>
#include <plugins/pychrysalide/helpers.h>
-#include "collection.h"
-#include "line.h"
#include "../node.h"
-#define YAML_NODE_DOC \
- "YamlNode handles a node in a Yaml tree.\n" \
- "\n" \
- "There are three kinds of node contents defined in the Yaml specifications:\n" \
- "* scalar, implemented by the pychrysalide.plugins.yaml.YamlScalar object.\n" \
- "* sequence and mapping, implemented by the pychrysalide.plugins.yaml.YamlCollection object."
-
-
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(yaml_node, G_TYPE_YAML_NODE, NULL);
-/* Recherche les noeuds correspondant à un chemin. */
-static PyObject *py_yaml_node_find_by_path(PyObject *, PyObject *);
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_yaml_node_init(PyObject *, PyObject *, PyObject *);
-/* Recherche l'unique noeud correspondant à un chemin. */
-static PyObject *py_yaml_node_find_one_by_path(PyObject *, PyObject *);
-
-/* Fournit la ligne d'origine associée à un noeud. */
-static PyObject *py_yaml_node_get_yaml_line(PyObject *, void *);
+/* Recherche le premier noeud correspondant à un chemin. */
+static PyObject *py_yaml_node_find_first_by_path(PyObject *, PyObject *);
/******************************************************************************
* *
-* Paramètres : self = variable non utilisée ici. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
* *
-* Description : Recherche les noeuds correspondant à un chemin. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Liste de noeuds trouvés, éventuellement vide. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_node_find_by_path(PyObject *self, PyObject *args)
+static int py_yaml_node_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
- int prepare; /* Orientation des résultats */
- const char *path; /* Chemin d'accès à traiter */
int ret; /* Bilan de lecture des args. */
- GYamlNode *node; /* Version GLib du noeud */
- GYamlNode **found; /* Créations GLib à transmettre*/
- size_t count; /* Quantité de trouvailles */
- size_t i; /* Boucle de parcours */
-
-#define YAML_NODE_FIND_BY_PATH_METHOD PYTHON_METHOD_DEF \
-( \
- find_by_path, "path, /, prepare=False", \
- METH_VARARGS, py_yaml_node, \
- "Find nodes from a Yaml node using a path.\n" \
- "\n" \
- "Paths are node keys separated by '/', such as '/my/path/to/node'." \
- "\n" \
- "In case where the path ends with a trailing '/', the operation can" \
- " be used to prepare a further look by returning a node which can be" \
- " searched by a new call to this function instead of returning all its" \
- " contained nodes." \
-)
-
- prepare = 0;
- ret = PyArg_ParseTuple(args, "s|p", &path, &prepare);
- if (!ret) return NULL;
-
- node = G_YAML_NODE(pygobject_get(self));
-
- g_yaml_node_find_by_path(node, path, prepare, &found, &count);
-
- result = PyTuple_New(count);
-
- for (i = 0; i < count; i++)
- {
-#ifndef NDEBUG
- ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i])));
- assert(ret == 0);
-#else
- PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i])));
-#endif
-
- g_object_unref(G_OBJECT(found[i]));
+#define YAML_NODE_DOC \
+ "YamlNode handles a node in a YAML tree.\n" \
+ "\n" \
+ "There are two kinds of node contents defined in the YAML specifications:\n" \
+ "* pair, implemented by the pychrysalide.plugins.yaml.YamlPair object;\n" \
+ "* sequence and mapping, implemented by the pychrysalide.plugins.yaml.YamlCollection object."
- }
+ /* Initialisation d'un objet GLib */
- if (found != NULL)
- free(found);
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
- return result;
+ return 0;
}
@@ -132,103 +86,55 @@ static PyObject *py_yaml_node_find_by_path(PyObject *self, PyObject *args)
* Paramètres : self = variable non utilisée ici. *
* args = arguments fournis à l'appel. *
* *
-* Description : Recherche l'unique noeud correspondant à un chemin. *
+* Description : Recherche le premier noeud correspondant à un chemin. *
* *
-* Retour : Noeud avec correspondance établie ou None. *
+* Retour : Noeud avec la correspondance établie ou None si non trouvé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_node_find_one_by_path(PyObject *self, PyObject *args)
+static PyObject *py_yaml_node_find_first_by_path(PyObject *self, PyObject *args)
{
PyObject *result; /* Instance à retourner */
- int prepare; /* Orientation des résultats */
const char *path; /* Chemin d'accès à traiter */
int ret; /* Bilan de lecture des args. */
GYamlNode *node; /* Version GLib du noeud */
- GYamlNode *found; /* Création GLib à transmettre */
+ GYamlNode *found; /* Créations GLib à transmettre*/
-#define YAML_NODE_FIND_ONE_BY_PATH_METHOD PYTHON_METHOD_DEF \
+#define YAML_NODE_FIND_FIRST_BY_PATH_METHOD PYTHON_METHOD_DEF \
( \
- find_one_by_path, "path, /, prepare=False", \
+ find_first_by_path, "path", \
METH_VARARGS, py_yaml_node, \
- "Find a given node from a Yaml node using a path.\n" \
+ "Find the first node related to a path among the node YAML children.\n" \
"\n" \
"Paths are node keys separated by '/', such as '/my/path/to/node'." \
+ " In case where the path ends with a trailing '/', the operation" \
+ " matches the first next met node.\n" \
"\n" \
- "Only one node has to match the path for the function success." \
+ "The *path* argument is expected to be a string value.\n" \
"\n" \
- "In case where the path ends with a trailing '/', the operation can" \
- " be used to prepare a further look by returning a node which can be" \
- " searched by a new call to this function instead of returning all its" \
- " contained nodes." \
+ "The function returns a pychrysalide.plugins.yaml.YamlNode instance," \
+ " or *None* if none found." \
)
- prepare = 0;
-
- ret = PyArg_ParseTuple(args, "s|p", &path, &prepare);
+ ret = PyArg_ParseTuple(args, "s", &path);
if (!ret) return NULL;
node = G_YAML_NODE(pygobject_get(self));
- found = g_yaml_node_find_one_by_path(node, path, prepare);
+ found = g_yaml_node_find_first_by_path(node, path);
- if (found == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
- else
+ if (found != NULL)
{
result = pygobject_new(G_OBJECT(found));
g_object_unref(G_OBJECT(found));
}
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit la ligne principale associée à un noeud. *
-* *
-* Retour : Ligne Yaml à l'origine du noeud. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_node_get_yaml_line(PyObject *self, void *closure)
-{
- PyObject *result; /* Résultat à retourner */
- GYamlNode *node; /* Version GLib du noeud */
- GYamlLine *line; /* Line Yaml associée */
-
-#define YAML_NODE_YAML_LINE_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- yaml_line, py_yaml_node, \
- "Orginal Yaml line linked to the node." \
-)
-
- node = G_YAML_NODE(pygobject_get(self));
-
- line = g_yaml_node_get_yaml_line(node);
-
- if (line == NULL)
+ else
{
result = Py_None;
Py_INCREF(result);
}
- else
- {
- result = pygobject_new(G_OBJECT(line));
- g_object_unref(G_OBJECT(line));
- }
return result;
@@ -250,13 +156,11 @@ static PyObject *py_yaml_node_get_yaml_line(PyObject *self, void *closure)
PyTypeObject *get_python_yaml_node_type(void)
{
static PyMethodDef py_yaml_node_methods[] = {
- YAML_NODE_FIND_BY_PATH_METHOD,
- YAML_NODE_FIND_ONE_BY_PATH_METHOD,
+ YAML_NODE_FIND_FIRST_BY_PATH_METHOD,
{ NULL }
};
static PyGetSetDef py_yaml_node_getseters[] = {
- YAML_NODE_YAML_LINE_ATTRIB,
{ NULL }
};
@@ -273,7 +177,9 @@ PyTypeObject *get_python_yaml_node_type(void)
.tp_methods = py_yaml_node_methods,
.tp_getset = py_yaml_node_getseters,
- .tp_new = no_python_constructor_allowed
+
+ .tp_init = py_yaml_node_init,
+ .tp_new = py_yaml_node_new,
};
@@ -284,7 +190,7 @@ PyTypeObject *get_python_yaml_node_type(void)
/******************************************************************************
* *
-* Paramètres : module = module dont la définition est à compléter. *
+* Paramètres : - *
* *
* Description : Prend en charge l'objet 'pychrysalide.plugins.....YamlNode. *
* *
@@ -294,17 +200,24 @@ PyTypeObject *get_python_yaml_node_type(void)
* *
******************************************************************************/
-bool register_python_yaml_node(PyObject *module)
+bool ensure_python_yaml_node_is_registered(void)
{
PyTypeObject *type; /* Type Python 'YamlNode' */
+ PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
type = get_python_yaml_node_type();
- dict = PyModule_GetDict(module);
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.yaml");
+
+ dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_NODE, type, &PyGObject_Type))
- return false;
+ if (!register_class_for_pygobject(dict, G_TYPE_YAML_NODE, type))
+ return false;
+
+ }
return true;
@@ -316,7 +229,7 @@ bool register_python_yaml_node(PyObject *module)
* 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 noeud d'arborescence de format Yaml. *
+* Description : Tente de convertir en noeud d'arborescence de format YAML. *
* *
* Retour : Bilan de l'opération, voire indications supplémentaires. *
* *
@@ -338,7 +251,7 @@ int convert_to_yaml_node(PyObject *arg, void *dst)
break;
case 0:
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Yaml node");
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to YAML node");
break;
case 1:
diff --git a/plugins/yaml/python/node.h b/plugins/yaml/python/node.h
index dc3686b..80d8a65 100644
--- a/plugins/yaml/python/node.h
+++ b/plugins/yaml/python/node.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* node.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/node.h"
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -35,9 +35,9 @@
PyTypeObject *get_python_yaml_node_type(void);
/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlNode'. */
-bool register_python_yaml_node(PyObject *);
+bool ensure_python_yaml_node_is_registered(void);
-/* Tente de convertir en noeud d'arborescence de format Yaml. */
+/* Tente de convertir en noeud d'arborescence de format YAML. */
int convert_to_yaml_node(PyObject *, void *);
diff --git a/plugins/yaml/python/pair.c b/plugins/yaml/python/pair.c
index db5597d..1fffbeb 100644
--- a/plugins/yaml/python/pair.c
+++ b/plugins/yaml/python/pair.c
@@ -26,74 +26,176 @@
#include <assert.h>
+#include <malloc.h>
#include <pygobject.h>
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
#include <plugins/pychrysalide/helpers.h>
#include "collection.h"
-#include "line.h"
+#include "constants.h"
#include "node.h"
-#include "../pair.h"
+#include "../pair-int.h"
-/* Crée un nouvel objet Python de type 'YamlPair'. */
-static PyObject *py_yaml_pair_new(PyTypeObject *, PyObject *, PyObject *);
+CREATE_DYN_CONSTRUCTOR(yaml_pair, G_TYPE_YAML_PAIR);
-/* Fournit la clef représentée dans une paire en Yaml. */
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_yaml_pair_init(PyObject *, PyObject *, PyObject *);
+
+/* Rassemble une éventuelle séquence de valeurs attachées. */
+static PyObject *py_yaml_pair_aggregate_value(PyObject *, PyObject *);
+
+/* Fournit la clef représentée dans une paire en YAML. */
static PyObject *py_yaml_pair_get_key(PyObject *, void *);
-/* Fournit l'éventuelle valeur d'une paire en Yaml. */
+/* Indique le format d'origine YAML associé à la clef. */
+static PyObject *py_yaml_pair_get_key_style(PyObject *, void *);
+
+/* Fournit l'éventuelle valeur d'une paire en YAML. */
static PyObject *py_yaml_pair_get_value(PyObject *, void *);
-/* Attache une collection de noeuds Yaml à un noeud. */
-static int py_yaml_pair_set_collection(PyObject *, PyObject *, void *);
+/* Indique le format d'origine YAML associé à la clef. */
+static PyObject *py_yaml_pair_get_value_style(PyObject *, void *);
+
+/* Attache une collection de noeuds YAML à un noeud. */
+static int py_yaml_pair_set_children(PyObject *, PyObject *, void *);
/* Fournit une éventuelle collection rattachée à un noeud. */
-static PyObject *py_yaml_pair_get_collection(PyObject *, void *);
+static PyObject *py_yaml_pair_get_children(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
+* Paramètres : self = objet à initialiser (théoriquement). *
* args = arguments fournis à l'appel. *
* kwds = arguments de type key=val fournis. *
* *
-* Description : Crée un nouvel objet Python de type 'YamlPair'. *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
* *
-* Retour : Instance Python mise en place. *
+* Retour : 0. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_pair_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_yaml_pair_init(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *result; /* Instance à retourner */
- GYamlLine *key; /* Ligne principale du noeud */
+ YamlOriginalStyle kstyle; /* Format d'origine de la clef */
+ const char *value; /* Eventuelle valeur associée */
+ YamlOriginalStyle vstyle; /* Format d'origine de la val. */
+ const char *key; /* Clef associée au noeud */
int ret; /* Bilan de lecture des args. */
- GYamlPair *node; /* Création GLib à transmettre */
+ GYamlPair *pair; /* Création GLib à transmettre */
#define YAML_PAIR_DOC \
- "YamlPair handles a key/value pair node in a Yaml tree.\n" \
+ "YamlPair handles a key/value pair node in a YAML tree.\n" \
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " YamlPair(line)\n" \
+ " YamlPair(key, kstyle=PLAIN, value=None, vstyle=PLAIN)\n" \
+ "\n" \
+ "Where *key* defines the name for the YAML node, and *value*" \
+ " provides an optional direct value for the node. The *kstyle* and" \
+ " *vstyle* arguements are" \
+ " pychrysalide.plugins.yaml.YamlPair.YamlOriginalStyle states" \
+ " linking an original format to the provided relative strings.\n" \
+ "\n" \
+ "The two style are mainly used to aggregate children values into" \
+ " a raw array. The following declarations are indeed equivalent" \
+ " and pychrysalide.plugins.yaml.YamlPair.aggregate_value()" \
+ " build the latter version from the former one:\n" \
"\n" \
- "Where key is the original Yaml line for the pair."
+ "a: [ 1, 2, 3 ]\n" \
+ "\n" \
+ "a:\n" \
+ " - 1\n" \
+ " - 2\n" \
+ " - 3" \
+
+ /* Récupération des paramètres */
+
+ kstyle = YOS_PLAIN;
+ value = NULL;
+ vstyle = YOS_PLAIN;
+
+ ret = PyArg_ParseTuple(args, "s|O&sO&",
+ &key, convert_to_yaml_pair_original_style, &kstyle,
+ &value, convert_to_yaml_pair_original_style, &vstyle);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ pair = G_YAML_PAIR(pygobject_get(self));
+
+ if (!g_yaml_pair_create(pair, key, kstyle, value, vstyle))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create YAML pair."));
+ return -1;
+
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = serveur à manipuler. *
+* args = arguments d'appel non utilisés ici. *
+* *
+* Description : Rassemble une éventuelle séquence de valeurs attachées. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_yaml_pair_aggregate_value(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GYamlPair *node; /* Version GLib du type */
+ char *value; /* Chaîne à transmettre */
- ret = PyArg_ParseTuple(args, "O&", &convert_to_yaml_line, &key);
- if (!ret) return NULL;
+#define YAML_PAIR_AGGREGATE_VALUE_METHOD PYTHON_METHOD_DEF \
+( \
+ aggregate_value, "$self, /", \
+ METH_NOARGS, py_yaml_pair, \
+ "Provide the value linked to the YAML node, rebuilding" \
+ " it from inner sequenced values if necessary and" \
+ " possible." \
+ "\n" \
+ "The result is a string value, or *None* if none" \
+ " available." \
+)
- node = g_yaml_pair_new(key);
+ node = G_YAML_PAIR(pygobject_get(self));
+
+ value = g_yaml_pair_aggregate_value(node);
+
+ if (value == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
- g_object_ref_sink(G_OBJECT(node));
- result = pygobject_new(G_OBJECT(node));
- g_object_unref(node);
+ else
+ {
+ result = PyUnicode_FromString(value);
+ free(value);
+ }
return result;
@@ -105,7 +207,7 @@ static PyObject *py_yaml_pair_new(PyTypeObject *type, PyObject *args, PyObject *
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Fournit la clef représentée dans une paire en Yaml. *
+* Description : Fournit la clef représentée dans une paire en YAML. *
* *
* Retour : Clef sous forme de chaîne de caractères. *
* *
@@ -122,7 +224,8 @@ static PyObject *py_yaml_pair_get_key(PyObject *self, void *closure)
#define YAML_PAIR_KEY_ATTRIB PYTHON_GET_DEF_FULL \
( \
key, py_yaml_pair, \
- "Key linked to the Yaml key/value pair node." \
+ "Key linked to the YAML key/value pair node," \
+ " as a string value." \
)
node = G_YAML_PAIR(pygobject_get(self));
@@ -142,7 +245,45 @@ static PyObject *py_yaml_pair_get_key(PyObject *self, void *closure)
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
-* Description : Fournit l'éventuelle valeur d'une paire en Yaml. *
+* Description : Indique le format d'origine YAML associé à la clef. *
+* *
+* Retour : Valeur renseignée lors du chargement du noeud. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_yaml_pair_get_key_style(PyObject *self, void *closure)
+{
+ PyObject *result; /* Résultat à retourner */
+ GYamlPair *node; /* Version GLib du noeud */
+ YamlOriginalStyle style; /* Format à transmettre */
+
+#define YAML_PAIR_KEY_STYLE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ key_style, py_yaml_pair, \
+ "Original format for the YAML node Key, as a" \
+ " pychrysalide.plugins.yaml.YamlPair.YamlOriginalStyle" \
+ " value." \
+)
+
+ node = G_YAML_PAIR(pygobject_get(self));
+
+ style = g_yaml_pair_get_key_style(node);
+
+ result = cast_with_constants_group_from_type(get_python_yaml_pair_type(), "YamlOriginalStyle", style);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit l'éventuelle valeur d'une paire en YAML. *
* *
* Retour : Valeur sous forme de chaîne de caractères ou None. *
* *
@@ -159,7 +300,8 @@ static PyObject *py_yaml_pair_get_value(PyObject *self, void *closure)
#define YAML_PAIR_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
( \
value, py_yaml_pair, \
- "Value linked to the Yaml key/value pair node or None." \
+ "Value linked to the YAML key/value pair node, as a" \
+ " string value, or *None* if none defined." \
)
node = G_YAML_PAIR(pygobject_get(self));
@@ -182,11 +324,52 @@ static PyObject *py_yaml_pair_get_value(PyObject *self, void *closure)
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le format d'origine YAML associé à la clef. *
+* *
+* Retour : Valeur renseignée lors du chargement du noeud. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_yaml_pair_get_value_style(PyObject *self, void *closure)
+{
+ PyObject *result; /* Résultat à retourner */
+ GYamlPair *node; /* Version GLib du noeud */
+ YamlOriginalStyle style; /* Format à transmettre */
+
+#define YAML_PAIR_VALUE_STYLE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ value_style, py_yaml_pair, \
+ "Original format for the YAML node Value, as a" \
+ " pychrysalide.plugins.yaml.YamlPair.YamlOriginalStyle" \
+ " value.\n" \
+ "\n" \
+ "Even if there is no value for the node, the default" \
+ " style is returned: *PLAIN*." \
+)
+
+ node = G_YAML_PAIR(pygobject_get(self));
+
+ style = g_yaml_pair_get_value_style(node);
+
+ result = cast_with_constants_group_from_type(get_python_yaml_pair_type(), "YamlOriginalStyle", style);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = contenu binaire à manipuler. *
-* value = collection de noeuds Yaml. *
+* value = collection de noeuds YAML. *
* closure = adresse non utilisée ici. *
* *
-* Description : Attache une collection de noeuds Yaml à un noeud. *
+* Description : Attache une collection de noeuds YAML à un noeud. *
* *
* Retour : Jeu d'attributs liés au contenu courant. *
* *
@@ -194,28 +377,28 @@ static PyObject *py_yaml_pair_get_value(PyObject *self, void *closure)
* *
******************************************************************************/
-static int py_yaml_pair_set_collection(PyObject *self, PyObject *value, void *closure)
+static int py_yaml_pair_set_children(PyObject *self, PyObject *value, void *closure)
{
int result; /* Bilan à renvoyer */
GYamlPair *node; /* Version GLib du noeud */
- GYamlCollection *collec; /* Version GLib de la valeur */
+ GYamlCollection *children; /* Version GLib de la valeur */
node = G_YAML_PAIR(pygobject_get(self));
if (value == Py_None)
{
- g_yaml_pair_set_collection(node, NULL);
+ g_yaml_pair_set_children(node, NULL);
result = 0;
}
else
{
- if (!convert_to_yaml_collection(value, &collec))
+ if (!convert_to_yaml_collection(value, &children))
result = -1;
else
{
- g_yaml_pair_set_collection(node, collec);
+ g_yaml_pair_set_children(node, children);
result = 0;
}
@@ -233,29 +416,31 @@ static int py_yaml_pair_set_collection(PyObject *self, PyObject *value, void *cl
* *
* Description : Fournit une éventuelle collection rattachée à un noeud. *
* *
-* Retour : Collection de noeuds Yaml ou None. *
+* Retour : Collection de noeuds YAML ou None. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_yaml_pair_get_collection(PyObject *self, void *closure)
+static PyObject *py_yaml_pair_get_children(PyObject *self, void *closure)
{
PyObject *result; /* Instance à retourner */
GYamlPair *node; /* Version GLib du noeud */
- GYamlCollection *collec; /* Collection à transmettre */
-
-#define YAML_PAIR_COLLECTION_ATTRIB PYTHON_GETSET_DEF_FULL \
-( \
- collection, py_yaml_pair, \
- "Provide or define the collection of nodes attached to another Yaml node." \
+ GYamlCollection *children; /* Collection à transmettre */
+
+#define YAML_PAIR_CHILDREN_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ children, py_yaml_pair, \
+ "Provide or define the collection of nodes attached to another" \
+ " YAML node. The collection, if defined, is handled as a" \
+ " pychrysalide.plugins.yaml.YamlCollection instance." \
)
node = G_YAML_PAIR(pygobject_get(self));
- collec = g_yaml_pair_get_collection(node);
+ children = g_yaml_pair_get_children(node);
- if (collec == NULL)
+ if (children == NULL)
{
result = Py_None;
Py_INCREF(result);
@@ -263,8 +448,8 @@ static PyObject *py_yaml_pair_get_collection(PyObject *self, void *closure)
else
{
- result = pygobject_new(G_OBJECT(collec));
- g_object_unref(collec);
+ result = pygobject_new(G_OBJECT(children));
+ g_object_unref(children);
}
return result;
@@ -287,13 +472,16 @@ static PyObject *py_yaml_pair_get_collection(PyObject *self, void *closure)
PyTypeObject *get_python_yaml_pair_type(void)
{
static PyMethodDef py_yaml_pair_methods[] = {
+ YAML_PAIR_AGGREGATE_VALUE_METHOD,
{ NULL }
};
static PyGetSetDef py_yaml_pair_getseters[] = {
YAML_PAIR_KEY_ATTRIB,
+ YAML_PAIR_KEY_STYLE_ATTRIB,
YAML_PAIR_VALUE_ATTRIB,
- YAML_PAIR_COLLECTION_ATTRIB,
+ YAML_PAIR_VALUE_STYLE_ATTRIB,
+ YAML_PAIR_CHILDREN_ATTRIB,
{ NULL }
};
@@ -310,7 +498,9 @@ PyTypeObject *get_python_yaml_pair_type(void)
.tp_methods = py_yaml_pair_methods,
.tp_getset = py_yaml_pair_getseters,
- .tp_new = py_yaml_pair_new
+
+ .tp_init = py_yaml_pair_init,
+ .tp_new = py_yaml_pair_new,
};
@@ -321,7 +511,7 @@ PyTypeObject *get_python_yaml_pair_type(void)
/******************************************************************************
* *
-* Paramètres : module = module dont la définition est à compléter. *
+* Paramètres : - *
* *
* Description : Prend en charge l'objet 'pychrysalide.plugins.....YamlPair. *
* *
@@ -331,17 +521,27 @@ PyTypeObject *get_python_yaml_pair_type(void)
* *
******************************************************************************/
-bool register_python_yaml_pair(PyObject *module)
+bool ensure_python_yaml_pair_is_registered(void)
{
PyTypeObject *type; /* Type Python 'YamlPair' */
+ PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
type = get_python_yaml_pair_type();
- dict = PyModule_GetDict(module);
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.yaml");
+
+ dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_PAIR, type, get_python_yaml_node_type()))
- return false;
+ if (!register_class_for_pygobject(dict, G_TYPE_YAML_PAIR, type))
+ return false;
+
+ if (!define_yaml_pair_constants(type))
+ return false;
+
+ }
return true;
@@ -353,7 +553,7 @@ bool register_python_yaml_pair(PyObject *module)
* 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 noeud d'arborescence de format Yaml. *
+* Description : Tente de convertir en noeud d'arborescence de format YAML. *
* *
* Retour : Bilan de l'opération, voire indications supplémentaires. *
* *
@@ -375,7 +575,7 @@ int convert_to_yaml_pair(PyObject *arg, void *dst)
break;
case 0:
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Yaml key/value pair");
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to YAML key/value pair");
break;
case 1:
diff --git a/plugins/yaml/python/pair.h b/plugins/yaml/python/pair.h
index 2cafab8..b03b984 100644
--- a/plugins/yaml/python/pair.h
+++ b/plugins/yaml/python/pair.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* pair.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/pair.h"
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -35,9 +35,9 @@
PyTypeObject *get_python_yaml_pair_type(void);
/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlPair'. */
-bool register_python_yaml_pair(PyObject *);
+bool ensure_python_yaml_pair_is_registered(void);
-/* Tente de convertir en noeud d'arborescence de format Yaml. */
+/* Tente de convertir en noeud d'arborescence de format YAML. */
int convert_to_yaml_pair(PyObject *, void *);
diff --git a/plugins/yaml/python/parser.c b/plugins/yaml/python/parser.c
new file mode 100644
index 0000000..35a9090
--- /dev/null
+++ b/plugins/yaml/python/parser.c
@@ -0,0 +1,186 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - équivalent Python du fichier "plugins/yaml/parser.c"
+ *
+ * Copyright (C) 2019-2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "parser.h"
+
+
+#include <pygobject.h>
+#include <string.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../parser.h"
+
+
+
+/* Crée une arborescence YAML pour contenu au format adapté. */
+static PyObject *py_yaml_parse_from_text(PyObject *, PyObject *);
+
+/* Crée une arborescence YAML pour fichier au format adapté. */
+static PyObject *py_yaml_parse_from_file(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = NULL car méthode statique. *
+* args = arguments fournis lors de l'appel à la fonction. *
+* *
+* Description : Crée une arborescence YAML pour contenu au format adapté. *
+* *
+* Retour : Arborescence YAML mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_yaml_parse_from_text(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ const char *text; /* Chaîne à traiter. */
+ int ret; /* Bilan de lecture des args. */
+ GYamlNode *root; /* Noeud racine obtenu */
+
+#define YAML_PARSE_FROM_TEXT_METHOD PYTHON_METHOD_DEF \
+( \
+ parse_from_text, "text, /", \
+ METH_VARARGS, py_yaml, \
+ "Parse a YAML content in order to build the relative YAML tree.\n" \
+ "\n" \
+ "The *text* argument is a string containg a markup content to" \
+ " parse.\n" \
+ "\n" \
+ "The result is a pychrysalide.plugins.yaml.YamlNode instance" \
+ " or None in case of error." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &text);
+ if (!ret) return NULL;
+
+ root = parse_yaml_from_text(text, strlen(text));
+
+ if (root != NULL)
+ {
+ result = pygobject_new(G_OBJECT(root));
+ g_object_unref(G_OBJECT(root));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = NULL car méthode statique. *
+* args = arguments fournis lors de l'appel à la fonction. *
+* *
+* Description : Crée une arborescence YAML pour fichier au format adapté. *
+* *
+* Retour : Arborescence YAML mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_yaml_parse_from_file(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ const char *filename; /* Chemin vers des définitions */
+ int ret; /* Bilan de lecture des args. */
+ GYamlNode *root; /* Noeud racine obtenu */
+
+#define YAML_PARSE_FROM_FILE_METHOD PYTHON_METHOD_DEF \
+( \
+ parse_from_file, "filename, /", \
+ METH_VARARGS, py_yaml, \
+ "Parse a YAML content in order to build the relative YAML tree.\n" \
+ "\n" \
+ "The *filename* argument is a string for a path pointing to a YAML" \
+ " content. This path can be either a real filename or a resource" \
+ " URI.\n" \
+ "\n" \
+ "The result is a pychrysalide.plugins.yaml.YamlNode instance" \
+ " or None in case of error." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &filename);
+ if (!ret) return NULL;
+
+ root = parse_yaml_from_file(filename);
+
+ if (root != NULL)
+ {
+ result = pygobject_new(G_OBJECT(root));
+ g_object_unref(G_OBJECT(root));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Définit une extension du module 'plugins.yaml' à compléter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_yaml_module_with_parsers(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Module à recompléter */
+
+ static PyMethodDef py_yaml_methods[] = {
+ YAML_PARSE_FROM_TEXT_METHOD,
+ YAML_PARSE_FROM_FILE_METHOD,
+ { NULL }
+ };
+
+ module = get_access_to_python_module("pychrysalide.plugins.yaml");
+
+ result = register_python_module_methods(module, py_yaml_methods);
+
+ return result;
+
+}
diff --git a/plugins/yaml/python/parser.h b/plugins/yaml/python/parser.h
new file mode 100644
index 0000000..18586ab
--- /dev/null
+++ b/plugins/yaml/python/parser.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/parser.h"
+ *
+ * Copyright (C) 2019-2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_YAML_PYTHON_PARSER_H
+#define _PLUGINS_YAML_PYTHON_PARSER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'plugins.yaml' à compléter. */
+bool populate_yaml_module_with_parsers(void);
+
+
+
+#endif /* _PLUGINS_YAML_PYTHON_PARSER_H */
diff --git a/plugins/yaml/python/reader.c b/plugins/yaml/python/reader.c
deleted file mode 100644
index f80623f..0000000
--- a/plugins/yaml/python/reader.c
+++ /dev/null
@@ -1,388 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * reader.c - équivalent Python du fichier "plugins/yaml/reader.c"
- *
- * 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 "reader.h"
-
-
-#include <pygobject.h>
-
-
-#include <plugins/pychrysalide/helpers.h>
-
-
-#include "../reader.h"
-
-
-
-#define YAML_READER_DOC \
- "YamlReader is the class which aims to provide a reader interface to Yaml content.\n" \
- "\n" \
- "When no input error, the Yaml content can be retrieved line by line or thanks to a tree."
-
-
-
-/* Crée un lecteur pour contenu au format Yaml. */
-static PyObject *py_yaml_reader_new_from_content(PyObject *, PyObject *);
-
-/* Crée un lecteur pour contenu au format Yaml. */
-static PyObject *py_yaml_reader_new_from_path(PyObject *, PyObject *);
-
-/* Fournit la liste des lignes lues depuis un contenu Yaml. */
-static PyObject *py_yaml_reader_get_lines(PyObject *, void *);
-
-/* Fournit l'arborescence associée à la lecture de lignes Yaml. */
-static PyObject *py_yaml_reader_get_tree(PyObject *, void *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : self = variable non utilisée ici. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Crée un lecteur pour contenu au format Yaml. *
-* *
-* Retour : Instance mise en place ou None en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_reader_new_from_content(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Instance à retourner */
- const char *content; /* Contenu brut au format Yaml */
- int length; /* Taille de ce contenu */
- int ret; /* Bilan de lecture des args. */
- GYamlReader *reader; /* Création GLib à transmettre */
-
-#define YAML_READER_NEW_FROM_CONTENT_METHOD PYTHON_METHOD_DEF \
-( \
- new_from_content, "content", \
- METH_STATIC | METH_VARARGS, py_yaml_reader, \
- "Load a Yaml content." \
-)
-
- /**
- * La taille doit être de type 'int' et non 'Py_ssize_t', sinon les 32 bits
- * de poids fort ne sont pas initialisés !
- */
-
- ret = PyArg_ParseTuple(args, "s#", &content, &length);
- if (!ret) return NULL;
-
- reader = g_yaml_reader_new_from_content(content, length);
-
- if (reader == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
-
- else
- {
- g_object_ref_sink(G_OBJECT(reader));
- result = pygobject_new(G_OBJECT(reader));
- g_object_unref(reader);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = variable non utilisée ici. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Crée un lecteur pour contenu au format Yaml. *
-* *
-* Retour : Instance mise en place ou None en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_reader_new_from_path(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Instance à retourner */
- const char *path; /* Chemin d'accès à un contenu */
- int ret; /* Bilan de lecture des args. */
- GYamlReader *reader; /* Création GLib à transmettre */
-
-#define YAML_READER_NEW_FROM_PATH_METHOD PYTHON_METHOD_DEF \
-( \
- new_from_path, "path", \
- METH_STATIC | METH_VARARGS, py_yaml_reader, \
- "Load a Yaml content from a path.\n" \
- "\n" \
- "The path can be a filename or a resource URI." \
-)
-
- ret = PyArg_ParseTuple(args, "s", &path);
- if (!ret) return NULL;
-
- reader = g_yaml_reader_new_from_path(path);
-
- if (reader == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
-
- else
- {
- g_object_ref_sink(G_OBJECT(reader));
- result = pygobject_new(G_OBJECT(reader));
- g_object_unref(reader);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit la liste des lignes lues depuis un contenu Yaml. *
-* *
-* Retour : Liste de lignes correspondant au contenu Yaml lu. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_reader_get_lines(PyObject *self, void *closure)
-{
- PyObject *result; /* Résultat à retourner */
- GYamlReader *reader; /* Version GLib du type */
- size_t count; /* Quantité de lignes à traiter*/
- GYamlLine **lines; /* Liste de lignes lues */
- size_t i; /* Boucle de parcours */
-#ifndef NDEBUG
- int ret; /* Bilan d'une insertion */
-#endif
-
-#define YAML_READER_LINES_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- lines, py_yaml_reader, \
- "List of Yaml lines processed by the reader." \
-)
-
- reader = G_YAML_READER(pygobject_get(self));
-
- lines = g_yaml_reader_get_lines(reader, &count);
-
- result = PyTuple_New(count);
-
- for (i = 0; i < count; i++)
- {
-#ifndef NDEBUG
- ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(lines[i])));
- assert(ret == 0);
-#else
- PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(lines[i])));
-#endif
-
- g_object_unref(G_OBJECT(lines[i]));
-
- }
-
- if (lines != NULL)
- free(lines);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit l'arborescence associée à la lecture de lignes Yaml. *
-* *
-* Retour : Arborescence constituée par la lecture du contenu Yaml. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_reader_get_tree(PyObject *self, void *closure)
-{
- PyObject *result; /* Résultat à retourner */
- GYamlReader *reader; /* Version GLib du type */
- GYamlTree *tree; /* Arborescence associée */
-
-#define YAML_READER_TREE_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- tree, py_yaml_reader, \
- "Tree of all nodes built from the Yaml content." \
-)
-
- reader = G_YAML_READER(pygobject_get(self));
-
- tree = g_yaml_reader_get_tree(reader);
-
- if (tree == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
- else
- {
- result = pygobject_new(G_OBJECT(tree));
- g_object_unref(G_OBJECT(tree));
- }
-
- 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_yaml_reader_type(void)
-{
- static PyMethodDef py_yaml_reader_methods[] = {
- YAML_READER_NEW_FROM_CONTENT_METHOD,
- YAML_READER_NEW_FROM_PATH_METHOD,
- { NULL }
- };
-
- static PyGetSetDef py_yaml_reader_getseters[] = {
- YAML_READER_LINES_ATTRIB,
- YAML_READER_TREE_ATTRIB,
- { NULL }
- };
-
- static PyTypeObject py_yaml_reader_type = {
-
- PyVarObject_HEAD_INIT(NULL, 0)
-
- .tp_name = "pychrysalide.plugins.yaml.YamlReader",
- .tp_basicsize = sizeof(PyGObject),
-
- .tp_flags = Py_TPFLAGS_DEFAULT,
-
- .tp_doc = YAML_READER_DOC,
-
- .tp_methods = py_yaml_reader_methods,
- .tp_getset = py_yaml_reader_getseters,
- .tp_new = no_python_constructor_allowed
-
- };
-
- return &py_yaml_reader_type;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : module = module dont la définition est à compléter. *
-* *
-* Description : Prend en charge l'objet 'pychrysalide.plugins.....YamlReader.*
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool register_python_yaml_reader(PyObject *module)
-{
- PyTypeObject *type; /* Type Python 'YamlReader' */
- PyObject *dict; /* Dictionnaire du module */
-
- type = get_python_yaml_reader_type();
-
- dict = PyModule_GetDict(module);
-
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_READER, type, &PyGObject_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 lecteur de données au format Yaml. *
-* *
-* Retour : Bilan de l'opération, voire indications supplémentaires. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int convert_to_yaml_reader(PyObject *arg, void *dst)
-{
- int result; /* Bilan à retourner */
-
- result = PyObject_IsInstance(arg, (PyObject *)get_python_yaml_reader_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 Yaml reader");
- break;
-
- case 1:
- *((GYamlReader **)dst) = G_YAML_READER(pygobject_get(arg));
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- return result;
-
-}
diff --git a/plugins/yaml/python/tree.c b/plugins/yaml/python/tree.c
deleted file mode 100644
index 7d28254..0000000
--- a/plugins/yaml/python/tree.c
+++ /dev/null
@@ -1,427 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * tree.c - équivalent Python du fichier "plugins/yaml/tree.c"
- *
- * Copyright (C) 2019-2020 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 "tree.h"
-
-
-#include <pygobject.h>
-
-
-#include <i18n.h>
-#include <plugins/pychrysalide/helpers.h>
-
-
-#include "line.h"
-#include "../tree.h"
-
-
-
-/* Crée un nouvel objet Python de type 'YamlTree'. */
-static PyObject *py_yaml_tree_new(PyTypeObject *, PyObject *, PyObject *);
-
-/* Recherche les noeuds correspondant à un chemin. */
-static PyObject *py_yaml_tree_find_by_path(PyObject *, PyObject *);
-
-/* Fournit le noeud constituant la racine d'arborescence Yaml. */
-static PyObject *py_yaml_tree_get_root(PyObject *, void *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type de l'objet à instancier. *
-* args = arguments fournis à l'appel. *
-* kwds = arguments de type key=val fournis. *
-* *
-* Description : Crée un nouvel objet Python de type 'YamlTree'. *
-* *
-* Retour : Instance Python mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_tree_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Instance à retourner */
- PyObject *tuple; /* Liste de lignes Yaml */
- int ret; /* Bilan de lecture des args. */
- size_t count; /* Nombre d'éléments présents */
- GYamlLine **lines; /* Lignes au format Yaml */
- GYamlTree *tree; /* Création GLib à transmettre */
- size_t i; /* Boucle de parcours #1 */
- PyObject *item; /* Elément de la liste fournie */
- size_t k; /* Boucle de parcours #2 */
-
-#define YAML_TREE_DOC \
- "YamlTree offers a hierarchical access to Yaml lines as a tree.\n" \
- "\n" \
- "Instances can be created using the following constructor:\n" \
- "\n" \
- " YamlTree(lines)" \
- "\n" \
- "Where lines are a tuple of Yaml lines used to built the tree."
-
- ret = PyArg_ParseTuple(args, "O!", &PyTuple_Type, &tuple);
- if (!ret) return NULL;
-
- count = PyTuple_Size(tuple);
-
- lines = (GYamlLine **)malloc(count * sizeof(GYamlLine *));
-
- tree = NULL;
-
- for (i = 0; i < count; i++)
- {
- item = PyTuple_GetItem(tuple, i);
-
- ret = convert_to_yaml_line(item, &lines[i]);
-
- if (ret == 0)
- g_object_ref(G_OBJECT(lines[i]));
-
- else
- goto arg_error;
-
- }
-
- tree = g_yaml_tree_new(lines, count);
-
- arg_error:
-
- for (k = 0; k < i; k++)
- g_object_unref(G_OBJECT(lines[i]));
-
- free(lines);
-
- /* S'il y a eu une erreur... */
- if (i < count) return NULL;
-
- if (tree == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
-
- else
- {
- g_object_ref_sink(G_OBJECT(tree));
- result = pygobject_new(G_OBJECT(tree));
- g_object_unref(tree);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = variable non utilisée ici. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Recherche les noeuds correspondant à un chemin. *
-* *
-* Retour : Liste de noeuds trouvés, éventuellement vide. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_tree_find_by_path(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Instance à retourner */
- int prepare; /* Orientation des résultats */
- const char *path; /* Chemin d'accès à traiter */
- int ret; /* Bilan de lecture des args. */
- GYamlTree *tree; /* Version GLib du type */
- GYamlNode **found; /* Créations GLib à transmettre*/
- size_t count; /* Quantité de trouvailles */
- size_t i; /* Boucle de parcours */
-
-#define YAML_TREE_FIND_BY_PATH_METHOD PYTHON_METHOD_DEF \
-( \
- find_by_path, "path, /, prepare=False", \
- METH_VARARGS, py_yaml_tree, \
- "Find nodes in a Yaml tree using a path.\n" \
- "\n" \
- "Paths are node keys separated by '/', such as '/my/path/to/node'." \
- "\n" \
- "In case where the path ends with a trailing '/', the operation can" \
- " be used to prepare a further look by returning a node which can be" \
- " searched by a new call to this function instead of returning all its" \
- " contained nodes." \
-)
-
- prepare = 0;
-
- ret = PyArg_ParseTuple(args, "s|p", &path, &prepare);
- if (!ret) return NULL;
-
- tree = G_YAML_TREE(pygobject_get(self));
-
- g_yaml_tree_find_by_path(tree, path, prepare, &found, &count);
-
- result = PyTuple_New(count);
-
- for (i = 0; i < count; i++)
- {
-#ifndef NDEBUG
- ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i])));
- assert(ret == 0);
-#else
- PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i])));
-#endif
-
- g_object_unref(G_OBJECT(found[i]));
-
- }
-
- if (found != NULL)
- free(found);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = variable non utilisée ici. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Recherche l'unique noeud correspondant à un chemin. *
-* *
-* Retour : Noeud avec correspondance établie ou None. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_tree_find_one_by_path(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Instance à retourner */
- int prepare; /* Orientation des résultats */
- const char *path; /* Chemin d'accès à traiter */
- int ret; /* Bilan de lecture des args. */
- GYamlTree *tree; /* Version GLib du type */
- GYamlNode *found; /* Création GLib à transmettre */
-
-#define YAML_TREE_FIND_ONE_BY_PATH_METHOD PYTHON_METHOD_DEF \
-( \
- find_one_by_path, "path, /, prepare=False", \
- METH_VARARGS, py_yaml_tree, \
- "Find a given node from a Yaml node using a path.\n" \
- "\n" \
- "Paths are node keys separated by '/', such as '/my/path/to/node'." \
- "\n" \
- "Only one node has to match the path for the function success." \
- "\n" \
- "In case where the path ends with a trailing '/', the operation can" \
- " be used to prepare a further look by returning a node which can be" \
- " searched by a new call to this function instead of returning all its" \
- " contained nodes." \
-)
-
- prepare = 0;
-
- ret = PyArg_ParseTuple(args, "s|p", &path, &prepare);
- if (!ret) return NULL;
-
- tree = G_YAML_TREE(pygobject_get(self));
-
- found = g_yaml_tree_find_one_by_path(tree, path, prepare);
-
- if (found == NULL)
- {
- result = Py_None;
- Py_INCREF(result);
- }
- else
- {
- result = pygobject_new(G_OBJECT(found));
- g_object_unref(G_OBJECT(found));
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit le noeud constituant la racine d'arborescence Yaml. *
-* *
-* Retour : Noeud constituant la racine de l'arborescence. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_yaml_tree_get_root(PyObject *self, void *closure)
-{
- PyObject *result; /* Résultat à retourner */
- GYamlTree *tree; /* Version GLib du type */
- GYamlNode *root; /* Noeud racine d'arborescence */
-
-#define YAML_TREE_ROOT_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- root, py_yaml_tree, \
- "Yaml node which is the root of the whole tree nodes." \
-)
-
- tree = G_YAML_TREE(pygobject_get(self));
-
- root = g_yaml_tree_get_root(tree);
-
- result = pygobject_new(G_OBJECT(root));
- g_object_unref(G_OBJECT(root));
-
- 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_yaml_tree_type(void)
-{
- static PyMethodDef py_yaml_tree_methods[] = {
- YAML_TREE_FIND_BY_PATH_METHOD,
- YAML_TREE_FIND_ONE_BY_PATH_METHOD,
- { NULL }
- };
-
- static PyGetSetDef py_yaml_tree_getseters[] = {
- YAML_TREE_ROOT_ATTRIB,
- { NULL }
- };
-
- static PyTypeObject py_yaml_tree_type = {
-
- PyVarObject_HEAD_INIT(NULL, 0)
-
- .tp_name = "pychrysalide.plugins.yaml.YamlTree",
- .tp_basicsize = sizeof(PyGObject),
-
- .tp_flags = Py_TPFLAGS_DEFAULT,
-
- .tp_doc = YAML_TREE_DOC,
-
- .tp_methods = py_yaml_tree_methods,
- .tp_getset = py_yaml_tree_getseters,
- .tp_new = py_yaml_tree_new
-
- };
-
- return &py_yaml_tree_type;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : module = module dont la définition est à compléter. *
-* *
-* Description : Prend en charge l'objet 'pychrysalide.plugins.....YamlTree. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool register_python_yaml_tree(PyObject *module)
-{
- PyTypeObject *type; /* Type Python 'YamlTree' */
- PyObject *dict; /* Dictionnaire du module */
-
- type = get_python_yaml_tree_type();
-
- dict = PyModule_GetDict(module);
-
- if (!register_class_for_pygobject(dict, G_TYPE_YAML_TREE, type, &PyGObject_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 arborescence de lignes au format Yaml. *
-* *
-* Retour : Bilan de l'opération, voire indications supplémentaires. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int convert_to_yaml_tree(PyObject *arg, void *dst)
-{
- int result; /* Bilan à retourner */
-
- result = PyObject_IsInstance(arg, (PyObject *)get_python_yaml_tree_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 Yaml tree");
- break;
-
- case 1:
- *((GYamlTree **)dst) = G_YAML_TREE(pygobject_get(arg));
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- return result;
-
-}
diff --git a/plugins/yaml/reader.h b/plugins/yaml/reader.h
deleted file mode 100644
index 3e5ce48..0000000
--- a/plugins/yaml/reader.h
+++ /dev/null
@@ -1,69 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * reader.h - prototypes pour le lecteur de contenu Yaml
- *
- * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef PLUGINS_YAML_READER_H
-#define PLUGINS_YAML_READER_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-#include "line.h"
-#include "tree.h"
-
-
-
-#define G_TYPE_YAML_READER g_yaml_reader_get_type()
-#define G_YAML_READER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_YAML_READER, GYamlReader))
-#define G_IS_YAML_READER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_YAML_READER))
-#define G_YAML_READER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_YAML_READER, GYamlReaderClass))
-#define G_IS_YAML_READER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_YAML_READER))
-#define G_YAML_READER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_YAML_READER, GYamlReaderClass))
-
-
-/* Lecteur de contenu Yaml (instance) */
-typedef struct _GYamlReader GYamlReader;
-
-/* Lecteur de contenu Yaml (classe) */
-typedef struct _GYamlReaderClass GYamlReaderClass;
-
-
-/* Indique le type défini pour un lecteur de contenu Yaml. */
-GType g_yaml_reader_get_type(void);
-
-/* Crée un lecteur pour contenu au format Yaml. */
-GYamlReader *g_yaml_reader_new_from_content(const char *, size_t);
-
-/* Crée un lecteur pour contenu au format Yaml. */
-GYamlReader *g_yaml_reader_new_from_path(const char *);
-
-/* Fournit la liste des lignes lues depuis un contenu Yaml. */
-GYamlLine **g_yaml_reader_get_lines(const GYamlReader *, size_t *);
-
-/* Fournit l'arborescence associée à la lecture de lignes Yaml. */
-GYamlTree *g_yaml_reader_get_tree(const GYamlReader *);
-
-
-
-#endif /* PLUGINS_YAML_READER_H */
diff --git a/plugins/yaml/scalar.h b/plugins/yaml/scalar.h
deleted file mode 100644
index 5403e85..0000000
--- a/plugins/yaml/scalar.h
+++ /dev/null
@@ -1,72 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * scalar.h - prototypes pour un noeud Yaml de type "scalar"
- *
- * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef PLUGINS_YAML_SCALAR_H
-#define PLUGINS_YAML_SCALAR_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-#include "line.h"
-#include "node.h"
-
-
-/* Depuis collection.h : collection de noeuds au format Yaml (instance) */
-typedef struct _GYamlCollection GYamlCollection;
-
-
-#define G_TYPE_YAML_SCALAR g_yaml_scalar_get_type()
-#define G_YAML_SCALAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_YAML_SCALAR, GYamlScalar))
-#define G_IS_YAML_SCALAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_YAML_SCALAR))
-#define G_YAML_SCALAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_YAML_SCALAR, GYamlScalarClass))
-#define G_IS_YAML_SCALAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_YAML_SCALAR))
-#define G_YAML_SCALAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_YAML_SCALAR, GYamlScalarClass))
-
-
-/* Noeud d'une arborescence au format Yaml (instance) */
-typedef struct _GYamlScalar GYamlScalar;
-
-/* Noeud d'une arborescence au format Yaml (classe) */
-typedef struct _GYamlScalarClass GYamlScalarClass;
-
-
-/* Indique le type défini pour un noeud d'arborescence Yaml. */
-GType g_yaml_scalar_get_type(void);
-
-/* Construit un noeud d'arborescence Yaml. */
-GYamlScalar *g_yaml_scalar_new(GYamlLine *);
-
-/* Fournit la ligne principale associée à un noeud. */
-GYamlLine *g_yaml_scalar_get_yaml_line(const GYamlScalar *);
-
-/* Attache une collection de noeuds Yaml à un noeud. */
-void g_yaml_scalar_set_collection(GYamlScalar *, GYamlCollection *);
-
-/* Fournit une éventuelle collection rattachée à un noeud. */
-GYamlCollection *g_yaml_scalar_get_collection(const GYamlScalar *);
-
-
-
-#endif /* PLUGINS_YAML_SCALAR_H */
diff --git a/plugins/yaml/tree.c b/plugins/yaml/tree.c
deleted file mode 100644
index 9125302..0000000
--- a/plugins/yaml/tree.c
+++ /dev/null
@@ -1,421 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * tree.c - ligne de contenu Yaml
- *
- * Copyright (C) 2019-2020 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 "tree.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include <i18n.h>
-#include <core/logs.h>
-
-
-#include "pair.h"
-#include "collection.h"
-
-
-
-/* Arborescence de lignes au format Yaml (instance) */
-struct _GYamlTree
-{
- GObject parent; /* A laisser en premier */
-
- GYamlNode *root; /* Racine des noeuds */
-
-};
-
-/* Arborescence de lignes au format Yaml (classe) */
-struct _GYamlTreeClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des arborescence de lignes Yaml. */
-static void g_yaml_tree_class_init(GYamlTreeClass *);
-
-/* Initialise une instance d'arborescence de lignes Yaml. */
-static void g_yaml_tree_init(GYamlTree *);
-
-/* Supprime toutes les références externes. */
-static void g_yaml_tree_dispose(GYamlTree *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_yaml_tree_finalize(GYamlTree *);
-
-/* Construit une collection de noeuds avec une arborescence. */
-static bool g_yaml_tree_build_node(GYamlCollection *, GYamlLine **, size_t, size_t, size_t *);
-
-
-
-/* Indique le type défini pour une arborescence de lignes au format Yaml. */
-G_DEFINE_TYPE(GYamlTree, g_yaml_tree, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des arborescence de lignes Yaml. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_yaml_tree_class_init(GYamlTreeClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_yaml_tree_dispose;
- object->finalize = (GObjectFinalizeFunc)g_yaml_tree_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tree = instance à initialiser. *
-* *
-* Description : Initialise une instance d'arborescence de lignes Yaml. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_yaml_tree_init(GYamlTree *tree)
-{
- tree->root = NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tree = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_yaml_tree_dispose(GYamlTree *tree)
-{
- g_clear_object(&tree->root);
-
- G_OBJECT_CLASS(g_yaml_tree_parent_class)->dispose(G_OBJECT(tree));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tree = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_yaml_tree_finalize(GYamlTree *tree)
-{
- G_OBJECT_CLASS(g_yaml_tree_parent_class)->finalize(G_OBJECT(tree));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : lines = ensemble de lignes à constituer en arborescence. *
-* count = taille de cet ensemble de lignes. *
-* *
-* Description : Construit une arborescence à partir de lignes Yaml. *
-* *
-* Retour : Instance mise en place ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GYamlTree *g_yaml_tree_new(GYamlLine **lines, size_t count)
-{
- GYamlTree *result; /* Structure à retourner */
- GYamlCollection *collec; /* Collection de noeuds */
- size_t indent; /* Indentation initiale */
- size_t processed; /* Quantité de noeuds traités */
- bool status; /* Bilan de construction */
-
- result = g_object_new(G_TYPE_YAML_TREE, NULL);
-
- if (count > 0)
- {
- collec = g_yaml_collection_new(g_yaml_line_is_list_item(lines[0]));
-
- result->root = G_YAML_NODE(collec);
-
- indent = g_yaml_line_count_indent(lines[0]);
- processed = 0;
-
- status = g_yaml_tree_build_node(collec, lines, count, indent, &processed);
-
- if (status)
- assert(processed == count);
-
- else
- {
- g_object_unref(G_OBJECT(result));
- result = NULL;
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : lines = ensemble de lignes à constituer en arborescence. *
-* count = taille de cet ensemble de lignes. *
-* expected = niveau d'identation attendu. *
-* cur = position courante dans les lignes. [OUT] *
-* *
-* Description : Construit une collection de noeuds avec une arborescence. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_yaml_tree_build_node(GYamlCollection *collec, GYamlLine **lines, size_t count, size_t expected, size_t *cur)
-{
- bool result; /* Bilan à retourner */
- bool first; /* Marque d'un premier élément */
- GYamlNode *last; /* Mémorisation du dernier */
- GYamlLine *line; /* Ligne de parcours courante */
- size_t indent; /* Indentation de ligne */
- bool is_item; /* Elément d'une liste ? */
- GYamlCollection *sub; /* Nouvelle sous-collection */
-
- result = true;
-
- first = true;
- last = NULL;
-
- for (; *cur < count; )
- {
- line = lines[*cur];
-
- indent = g_yaml_line_count_indent(line);
- is_item = g_yaml_line_is_list_item(line);
-
- /**
- * Si la première ligne traitée commence par un élément de liste,
- * alors un appel parent a constitué une collection qui n'est pas une séquence.
- *
- * L'objectif est de créer une simple association de 'clefs: valeurs'.
- *
- * Si la collection n'est pas adaptée, alors le parcours n'est pas encore
- * arrivé à ce stade de construction.
- */
- if (first && is_item && !g_yaml_collection_is_sequence(collec))
- {
- indent += 2; /* 2 == strlen("- ") */
- is_item = false;
- }
-
- first = false;
-
- /* Fin de l'ensemble courant */
- if (indent < expected)
- goto done;
-
- /* Début d'un sous-ensemble */
- else if (indent > expected)
- {
- if (last == NULL)
- {
- result = false;
- goto done;
- }
-
- sub = g_yaml_collection_new(is_item);
- g_yaml_pair_set_collection(G_YAML_PAIR(last), sub);
-
- result = g_yaml_tree_build_node(sub, lines, count, indent, cur);
- if (!result) goto done;
-
- }
-
- /* Elément de même niveau */
- else
- {
- if (is_item)
- {
- /* Vérification de cohérence */
- if (!g_yaml_collection_is_sequence(collec))
- {
- log_variadic_message(LMT_BAD_BINARY, _("A list item was expected at line %zu"),
- g_yaml_line_get_number(line));
-
- result = false;
- goto done;
-
- }
-
- sub = g_yaml_collection_new(false);
- g_yaml_collection_add_node(collec, G_YAML_NODE(sub));
-
- result = g_yaml_tree_build_node(sub, lines, count, expected + 2 /* 2 == strlen("- ") */, cur);
- if (!result) goto done;
-
- }
-
- else
- {
- /* Vérification de cohérence */
- if (g_yaml_collection_is_sequence(collec))
- {
- log_variadic_message(LMT_BAD_BINARY, _("A mapping item was expected at line %zu"),
- g_yaml_line_get_number(line));
-
-
- result = false;
- goto done;
-
- }
-
- last = G_YAML_NODE(g_yaml_pair_new(line));
-
- if (last == NULL)
- {
- result = false;
- goto done;
- }
-
- g_yaml_collection_add_node(collec, last);
-
- (*cur)++;
-
- }
-
- }
-
- }
-
- done:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tree = ligne au format Yaml à consulter. *
-* *
-* Description : Fournit le noeud constituant la racine d'arborescence Yaml. *
-* *
-* Retour : Noeud constituant la racine de l'arborescence. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GYamlNode *g_yaml_tree_get_root(const GYamlTree *tree)
-{
- GYamlNode *result; /* Liste à retourner */
-
- result = tree->root;
-
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tree = ligne au format Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* nodes = liste de noeuds avec correspondance établie. [OUT] *
-* count = quantité de ces noeuds. [OUT] *
-* *
-* Description : Recherche les noeuds correspondant à un chemin. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_yaml_tree_find_by_path(const GYamlTree *tree, const char *path, bool prepare, GYamlNode ***nodes, size_t *count)
-{
- g_yaml_node_find_by_path(tree->root, path, prepare, nodes, count);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tree = ligne au format Yaml à consulter. *
-* path = chemin d'accès à parcourir. *
-* prepare = indication sur une préparation d'un prochain appel.*
-* *
-* Description : Recherche l'unique noeud correspondant à un chemin. *
-* *
-* Retour : Noeud avec correspondance établie ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GYamlNode *g_yaml_tree_find_one_by_path(GYamlTree *tree, const char *path, bool prepare)
-{
- GYamlNode *result; /* Trouvaille unique à renvoyer*/
-
- result = g_yaml_node_find_one_by_path(tree->root, path, prepare);
-
- return result;
-
-}
diff --git a/plugins/yaml/tree.h b/plugins/yaml/tree.h
deleted file mode 100644
index bfe034a..0000000
--- a/plugins/yaml/tree.h
+++ /dev/null
@@ -1,69 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * tree.h - prototypes pour une ligne de contenu Yaml
- *
- * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef PLUGINS_YAML_TREE_H
-#define PLUGINS_YAML_TREE_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-#include "line.h"
-#include "node.h"
-
-
-
-#define G_TYPE_YAML_TREE g_yaml_tree_get_type()
-#define G_YAML_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_YAML_TREE, GYamlTree))
-#define G_IS_YAML_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_YAML_TREE))
-#define G_YAML_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_YAML_TREE, GYamlTreeClass))
-#define G_IS_YAML_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_YAML_TREE))
-#define G_YAML_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_YAML_TREE, GYamlTreeClass))
-
-
-/* Arborescence de lignes au format Yaml (instance) */
-typedef struct _GYamlTree GYamlTree;
-
-/* Arborescence de lignes au format Yaml (classe) */
-typedef struct _GYamlTreeClass GYamlTreeClass;
-
-
-/* Indique le type défini pour une arborescence de lignes au format Yaml. */
-GType g_yaml_tree_get_type(void);
-
-/* Construit une arborescence à partir de lignes Yaml. */
-GYamlTree *g_yaml_tree_new(GYamlLine **, size_t);
-
-/* Fournit le noeud constituant la racine d'arborescence Yaml. */
-GYamlNode *g_yaml_tree_get_root(const GYamlTree *);
-
-/* Recherche les noeuds correspondant à un chemin. */
-void g_yaml_tree_find_by_path(const GYamlTree *, const char *, bool, GYamlNode ***, size_t *);
-
-/* Recherche l'unique noeud correspondant à un chemin. */
-GYamlNode *g_yaml_tree_find_one_by_path(GYamlTree *, const char *, bool);
-
-
-
-#endif /* PLUGINS_YAML_TREE_H */