summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide')
-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
178 files changed, 11142 insertions, 2157 deletions
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 */