summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am75
-rw-r--r--src/analysis/contents/encapsulated.c2
-rw-r--r--src/analysis/contents/file.c2
-rw-r--r--src/analysis/contents/memory.c4
-rw-r--r--src/analysis/contents/restricted.c2
-rw-r--r--src/analysis/scan/patterns/backends/Makefile.am8
-rw-r--r--src/analysis/storage/Makefile.am7
-rw-r--r--src/analysis/storage/serialize.h64
-rw-r--r--src/analysis/storage/tpmem.h70
-rw-r--r--src/app.c (renamed from src/framework.c)349
-rw-r--r--src/app.h56
-rw-r--r--src/arch/Makefile.am52
-rw-r--r--src/arch/archbase.h6
-rw-r--r--src/arch/instruction-int.h126
-rw-r--r--src/arch/instruction-ui-int.h55
-rw-r--r--src/arch/instruction-ui.c254
-rw-r--r--src/arch/instruction-ui.h41
-rw-r--r--src/arch/instruction.c1935
-rw-r--r--src/arch/instruction.h316
-rw-r--r--src/arch/instructions/Makefile.am11
-rw-r--r--src/arch/instructions/raw-int.h56
-rw-r--r--src/arch/instructions/raw-ui.c261
-rw-r--r--src/arch/instructions/raw-ui.h37
-rw-r--r--src/arch/instructions/raw.c696
-rw-r--r--src/arch/instructions/raw.h41
-rw-r--r--src/arch/instructions/undefined-int.h52
-rw-r--r--src/arch/instructions/undefined-ui.c102
-rw-r--r--src/arch/instructions/undefined-ui.h37
-rw-r--r--src/arch/instructions/undefined.c383
-rw-r--r--src/arch/instructions/undefined.h28
-rw-r--r--src/arch/operand-int.h93
-rw-r--r--src/arch/operand-ui-int.h52
-rw-r--r--src/arch/operand-ui.c111
-rw-r--r--src/arch/operand-ui.h54
-rw-r--r--src/arch/operand.c653
-rw-r--r--src/arch/operand.h64
-rw-r--r--src/arch/operands/Makefile.am38
-rw-r--r--src/arch/operands/immediate-int.h66
-rw-r--r--src/arch/operands/immediate-ui.c184
-rw-r--r--src/arch/operands/immediate-ui.h37
-rw-r--r--src/arch/operands/immediate.c1320
-rw-r--r--src/arch/operands/immediate.h86
-rw-r--r--src/arch/operands/known-int.h55
-rw-r--r--src/arch/operands/known-ui.c79
-rw-r--r--src/arch/operands/known-ui.h37
-rw-r--r--src/arch/operands/known.c433
-rw-r--r--src/arch/operands/known.h26
-rw-r--r--src/arch/operands/register-int.h6
-rw-r--r--src/arch/operands/register-ui.c93
-rw-r--r--src/arch/operands/register-ui.h37
-rw-r--r--src/arch/operands/register.c371
-rw-r--r--src/arch/register-int.h24
-rw-r--r--src/arch/register.c225
-rw-r--r--src/arch/register.h33
-rw-r--r--src/arch/vmpa.h30
-rw-r--r--src/common/Makefile.am35
-rw-r--r--src/common/bits.c305
-rw-r--r--src/common/bits.h19
-rw-r--r--src/common/compiler.h16
-rw-r--r--src/common/cpp.h17
-rw-r--r--src/common/curl.c78
-rw-r--r--src/common/curl.h14
-rw-r--r--src/common/datatypes.h30
-rw-r--r--src/common/entropy.c88
-rw-r--r--src/common/entropy.h41
-rw-r--r--src/common/extstr.c2
-rw-r--r--src/common/fnv1a.c33
-rw-r--r--src/common/fnv1a.h6
-rw-r--r--src/common/io.h57
-rw-r--r--src/common/json.c203
-rw-r--r--src/common/json.h44
-rw-r--r--src/common/leb128.c252
-rw-r--r--src/common/leb128.h17
-rw-r--r--src/common/pathname.c23
-rw-r--r--src/common/pathname.h2
-rw-r--r--src/common/sort.h3
-rw-r--r--src/common/szbin.h282
-rw-r--r--src/common/szstr.h5
-rw-r--r--src/common/xdg.c338
-rw-r--r--src/common/xdg.h19
-rw-r--r--src/core/Makefile.am12
-rw-r--r--src/core/core.c101
-rw-r--r--src/core/core.h16
-rw-r--r--src/core/global.c190
-rw-r--r--src/core/global.h38
-rw-r--r--src/core/logs.h9
-rw-r--r--src/core/nox.c62
-rw-r--r--src/core/nox.h37
-rw-r--r--src/core/processors.c23
-rw-r--r--src/core/processors.h6
-rw-r--r--src/data/Makefile.am2
-rw-r--r--src/data/images/Makefile.am33
-rw-r--r--src/data/images/dock-station-bottom-symbolic.svg197
-rw-r--r--src/data/images/dock-station-left-symbolic.svg51
-rw-r--r--src/data/images/dock-station-right-symbolic.svg76
-rw-r--r--src/data/images/gresource.xml12
-rw-r--r--src/data/images/logs-symbolic.svg93
-rw-r--r--src/format/Makefile.am24
-rw-r--r--src/format/executable-int.c155
-rw-r--r--src/format/executable-int.h54
-rw-r--r--src/format/executable.c445
-rw-r--r--src/format/executable.h84
-rw-r--r--src/format/flat-int.h10
-rw-r--r--src/format/flat.c125
-rw-r--r--src/format/flat.h27
-rw-r--r--src/format/known-int.h18
-rw-r--r--src/format/known.c92
-rw-r--r--src/format/known.h33
-rw-r--r--src/format/program-int.h (renamed from src/format/format-int.h)65
-rw-r--r--src/format/program.c (renamed from src/format/format.c)318
-rw-r--r--src/format/program.h (renamed from src/format/format.h)122
-rw-r--r--src/framework.h66
-rw-r--r--src/glibext/Makefile.am102
-rw-r--r--src/glibext/bufferline.c334
-rw-r--r--src/glibext/bufferline.h14
-rw-r--r--src/glibext/comparable-int.h47
-rw-r--r--src/glibext/comparable.c124
-rw-r--r--src/glibext/comparable.h46
-rw-r--r--src/glibext/comparison-int.h58
-rw-r--r--src/glibext/comparison.c199
-rw-r--r--src/glibext/comparison.h80
-rw-r--r--src/glibext/hashable-int.h47
-rw-r--r--src/glibext/hashable.c82
-rw-r--r--src/glibext/hashable.h42
-rw-r--r--src/glibext/helpers.h29
-rw-r--r--src/glibext/log-int.h58
-rw-r--r--src/glibext/log.c306
-rw-r--r--src/glibext/log.h43
-rw-r--r--src/glibext/objhole-int.h169
-rw-r--r--src/glibext/objhole.c256
-rw-r--r--src/glibext/objhole.h118
-rw-r--r--src/glibext/options/Makefile.am3
-rw-r--r--src/glibext/options/asm.h65
-rw-r--r--src/glibext/portion-int-ui.h (renamed from src/glibext/gbinportion-int.h)0
-rw-r--r--src/glibext/portion-int.h69
-rw-r--r--src/glibext/portion-ui.c (renamed from src/glibext/gbinportion.c)0
-rw-r--r--src/glibext/portion-ui.h (renamed from src/glibext/gbinportion.h)0
-rw-r--r--src/glibext/portion.c974
-rw-r--r--src/glibext/portion.h121
-rw-r--r--src/glibext/secstorage-int.h60
-rw-r--r--src/glibext/secstorage.c950
-rw-r--r--src/glibext/secstorage.h74
-rw-r--r--src/glibext/serialize-int.h (renamed from src/analysis/storage/serialize-int.h)18
-rw-r--r--src/glibext/serialize.c (renamed from src/analysis/storage/serialize.c)28
-rw-r--r--src/glibext/serialize.h52
-rw-r--r--src/glibext/sigredir.c (renamed from src/glibext/signal.c)159
-rw-r--r--src/glibext/sigredir.h (renamed from src/glibext/_signal.h)21
-rw-r--r--src/glibext/singleton-int.h47
-rw-r--r--src/glibext/singleton.c341
-rw-r--r--src/glibext/singleton.h53
-rw-r--r--src/glibext/storage-int.h (renamed from src/analysis/storage/storage-int.h)23
-rw-r--r--src/glibext/storage.c (renamed from src/analysis/storage/storage.c)994
-rw-r--r--src/glibext/storage.h (renamed from src/analysis/storage/storage.h)70
-rw-r--r--src/glibext/strbuilder-int.h47
-rw-r--r--src/glibext/strbuilder.c89
-rw-r--r--src/glibext/strbuilder.h46
-rw-r--r--src/glibext/tpmem-int.h78
-rw-r--r--src/glibext/tpmem.c (renamed from src/analysis/storage/tpmem.c)224
-rw-r--r--src/glibext/tpmem.h57
-rw-r--r--src/glibext/widthtracker.c8
-rw-r--r--src/glibext/work-int.h31
-rw-r--r--src/glibext/work.c1213
-rw-r--r--src/glibext/work.h106
-rw-r--r--src/glibext/workgroup-int.h59
-rw-r--r--src/glibext/workgroup.c966
-rw-r--r--src/glibext/workgroup.h98
-rw-r--r--src/glibext/workqueue-int.h50
-rw-r--r--src/glibext/workqueue.c917
-rw-r--r--src/glibext/workqueue.h87
-rw-r--r--src/gtkext/Makefile.am37
-rw-r--r--src/gtkext/area.c2
-rw-r--r--src/gtkext/bindings/Makefile.am42
-rw-r--r--src/gtkext/bindings/generated-enums.c.template41
-rw-r--r--src/gtkext/bindings/generated-enums.h.template23
-rw-r--r--src/gtkext/bufferview.c20
-rw-r--r--src/gtkext/dockstation-int.h68
-rw-r--r--src/gtkext/dockstation.c1052
-rw-r--r--src/gtkext/dockstation.h (renamed from src/gtkext/gtkdockstation.h)47
-rw-r--r--src/gtkext/dockstation.ui80
-rw-r--r--src/gtkext/gresource.xml10
-rw-r--r--src/gtkext/grid-int.h81
-rw-r--r--src/gtkext/grid.c1128
-rw-r--r--src/gtkext/grid.h (renamed from src/gtkext/tiledgrid.h)81
-rw-r--r--src/gtkext/grid.ui217
-rw-r--r--src/gtkext/gtkdockstation.c467
-rw-r--r--src/gtkext/gtkstatusstack.c1121
-rw-r--r--src/gtkext/helpers.h43
-rw-r--r--src/gtkext/hexview.c301
-rw-r--r--src/gtkext/hexview.h6
-rw-r--r--src/gtkext/hexview.ui52
-rw-r--r--src/gtkext/launcher-int.h56
-rw-r--r--src/gtkext/launcher.c211
-rw-r--r--src/gtkext/launcher.h45
-rw-r--r--src/gtkext/launcher.ui76
-rw-r--r--src/gtkext/panel-int.h (renamed from src/gui/panel-int.h)50
-rw-r--r--src/gtkext/panel.c (renamed from src/gui/panel.c)206
-rw-r--r--src/gtkext/panel.h (renamed from src/gui/panel.h)38
-rw-r--r--src/gtkext/statusstack-int.h106
-rw-r--r--src/gtkext/statusstack.c1383
-rw-r--r--src/gtkext/statusstack.h (renamed from src/gtkext/gtkstatusstack.h)52
-rw-r--r--src/gtkext/statusstack.ui214
-rw-r--r--src/gtkext/tiledgrid.c1143
-rw-r--r--src/gtkext/tweak-int.h65
-rw-r--r--src/gtkext/tweak.c319
-rw-r--r--src/gtkext/tweak.h90
-rw-r--r--src/gtkext/tweak.ui46
-rw-r--r--src/gui/Makefile.am24
-rw-r--r--src/gui/core/Makefile.am5
-rw-r--r--src/gui/core/core.c22
-rw-r--r--src/gui/core/core.h1
-rw-r--r--src/gui/core/logs.c32
-rw-r--r--src/gui/core/nox.c48
-rw-r--r--src/gui/core/nox.h37
-rw-r--r--src/gui/core/panels.c423
-rw-r--r--src/gui/core/panels.h62
-rw-r--r--src/gui/dialogs/Makefile.am69
-rw-r--r--src/gui/dialogs/about-int.h55
-rw-r--r--src/gui/dialogs/about.c167
-rw-r--r--src/gui/dialogs/about.css9
-rw-r--r--src/gui/dialogs/about.h12
-rw-r--r--src/gui/dialogs/about.ui173
-rw-r--r--src/gui/dialogs/gresource.xml26
-rw-r--r--src/gui/dialogs/preferences-int.h62
-rw-r--r--src/gui/dialogs/preferences.c424
-rw-r--r--src/gui/dialogs/preferences.h16
-rw-r--r--src/gui/dialogs/preferences.ui247
-rw-r--r--src/gui/dialogs/prefs/Makefile.am34
-rw-r--r--src/gui/dialogs/prefs/appearance-int.h64
-rw-r--r--src/gui/dialogs/prefs/appearance.c251
-rw-r--r--src/gui/dialogs/prefs/appearance.h41
-rw-r--r--src/gui/dialogs/prefs/appearance.ui184
-rw-r--r--src/gui/dialogs/prefs/gresource.xml7
-rw-r--r--src/gui/dialogs/prefs/security-int.h64
-rw-r--r--src/gui/dialogs/prefs/security.c400
-rw-r--r--src/gui/dialogs/prefs/security.h41
-rw-r--r--src/gui/dialogs/prefs/security.ui170
-rw-r--r--src/gui/gresource.xml8
-rw-r--r--src/gui/panels/Makefile.am41
-rw-r--r--src/gui/panels/binary-int.h52
-rw-r--r--src/gui/panels/binary-params-int.h50
-rw-r--r--src/gui/panels/binary-params.c178
-rw-r--r--src/gui/panels/binary-params.h41
-rw-r--r--src/gui/panels/binary-params.ui42
-rw-r--r--src/gui/panels/binary.c195
-rw-r--r--src/gui/panels/binary.h48
-rw-r--r--src/gui/panels/binary.ui16
-rw-r--r--src/gui/panels/gresource.xml26
-rw-r--r--src/gui/panels/log.c451
-rw-r--r--src/gui/panels/log.h67
-rw-r--r--src/gui/panels/log.ui59
-rw-r--r--src/gui/panels/logs-col-icon.ui17
-rw-r--r--src/gui/panels/logs-col-message.ui19
-rw-r--r--src/gui/panels/logs-int.h53
-rw-r--r--src/gui/panels/logs.c227
-rw-r--r--src/gui/panels/logs.h47
-rw-r--r--src/gui/panels/logs.ui58
-rw-r--r--src/gui/panels/welcome-hints.txt23
-rw-r--r--src/gui/panels/welcome-int.h61
-rw-r--r--src/gui/panels/welcome.c881
-rw-r--r--src/gui/panels/welcome.h37
-rw-r--r--src/gui/panels/welcome.ui399
-rw-r--r--src/gui/style.css71
-rw-r--r--src/gui/window-int.h60
-rw-r--r--src/gui/window.c621
-rw-r--r--src/gui/window.h61
-rw-r--r--src/gui/window.ui79
-rw-r--r--src/plugins/Makefile.am19
-rw-r--r--src/plugins/dt.c545
-rw-r--r--src/plugins/dt.h50
-rw-r--r--src/plugins/manager-int.h54
-rw-r--r--src/plugins/manager.c113
-rw-r--r--src/plugins/manager.h61
-rw-r--r--src/plugins/native-int.h73
-rw-r--r--src/plugins/native.c295
-rw-r--r--src/plugins/native.h46
-rw-r--r--src/plugins/pglist.c424
-rw-r--r--src/plugins/pglist.h98
-rw-r--r--src/plugins/plugin-def.h16
-rw-r--r--src/plugins/plugin-int.h88
-rw-r--r--src/plugins/plugin.c966
-rw-r--r--src/plugins/plugin.h41
-rw-r--r--src/plugins/self.h99
-rw-r--r--src/plugins/tweakable-int.h50
-rw-r--r--src/plugins/tweakable.c98
-rw-r--r--src/plugins/tweakable.h62
-rw-r--r--src/rost.c10
-rw-r--r--src/schemas/re.chrysalide.framework.gschema.xml117
287 files changed, 26276 insertions, 17438 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1250b59..7411287 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
lib_LTLIBRARIES = libchrysacore4.la libchrysacoreui.la # libchrysacore.la
-bin_PROGRAMS = framework # chrysalide chrysalide-hub rost
+bin_PROGRAMS = chrysalide # chrysalide-hub rost
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/intl
@@ -39,18 +39,18 @@ GUI_SUBDIR = \
endif
-libchrysacore_la_LIBADD = \
- analysis/libanalysis.la \
- arch/libarch.la \
- common/libcommon.la \
- core/libcore.la \
- debug/libdebug.la \
- format/libformat.la \
- glibext/libglibext.la \
- $(GTKEXT_LIBADD) \
- $(GUI_LIBADD) \
- mangling/libmangling.la \
- plugins/libplugins.la
+# libchrysacore_la_LIBADD = \
+# analysis/libanalysis.la \
+# arch/libarch.la \
+# common/libcommon.la \
+# core/libcore.la \
+# debug/libdebug.la \
+# format/libformat.la \
+# glibext/libglibext.la \
+# $(GTKEXT_LIBADD) \
+# $(GUI_LIBADD) \
+# mangling/libmangling.la \
+# plugins/libplugins.la
# -ldl: dladdr(), dlerror()
@@ -59,7 +59,7 @@ libchrysacore_la_LDFLAGS = \
-avoid-version -ldl -lm \
$(TOOLKIT_LIBS) $(LIBXML_LIBS) \
$(LIBSQLITE_LIBS) $(LIBARCHIVE_LIBS) \
- $(LIBSSL_LIBS) $(LIBHS_LIBS)
+ $(LIBSSL_LIBS)
if BUILD_CURL_SUPPORT
@@ -73,19 +73,32 @@ libchrysacore_la_LDFLAGS += $(LIBMAGIC_LIBS)
endif
+if BUILD_HS_SUPPORT
+
+libchrysacore_la_LDFLAGS += $(LIBHS_LIBS)
+
+endif
+
libchrysacore4_la_SOURCES =
libchrysacore4_la_LIBADD = \
analysis/libanalysis4.la \
- arch/libarch4.la \
+ arch/libarch.la \
common/libcommon4.la \
core/libcore4.la \
- glibext/libglibext4.la \
+ format/libformat.la \
+ glibext/libglibext.la \
plugins/libplugins.la
libchrysacore4_la_LDFLAGS = \
- $(TOOLKIT_LIBS) $(LIBSSL_LIBS)
+ $(TOOLKIT_LIBS) $(LIBSSL_LIBS) $(LIBJSONGLIB_LIBS) $(LIBZIP_LIBS)
+
+if BUILD_CURL_SUPPORT
+
+libchrysacore4_la_LDFLAGS += $(LIBCURL_LIBS)
+
+endif
#--- libchrysacoreui
@@ -95,13 +108,15 @@ EXTRA_libchrysacoreui_la_DEPENDENCIES = libchrysacore4.la
libchrysacoreui_la_SOURCES =
libchrysacoreui_la_LIBADD = \
+ arch/libarchui.la \
+ data/images/libdataimages.la \
glibext/libglibextui.la \
gtkext/libgtkext4.la \
gui/libgui4.la
# -lm: log()
libchrysacoreui_la_LDFLAGS = \
- $(LIBGTK4_CFLAGS) -L.libs -lchrysacore4 \
+ $(LIBGTK4_LIBS) -L.libs -lchrysacore4 \
-lm
@@ -111,33 +126,33 @@ libchrysacoreui_la_LDFLAGS = \
# Programme principal
############################################################
-EXTRA_chrysalide_DEPENDENCIES = libchrysacore.la
+EXTRA_chrysalide0_DEPENDENCIES = libchrysacore.la
-chrysalide_SOURCES = \
+chrysalide0_SOURCES = \
$(GOBJECT_LEAKS_SOURCES) \
main.c
-chrysalide_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS)
+chrysalide0_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS)
-chrysalide_LDFLAGS = $(TOOLKIT_LIBS) -L/usr/X11R6/lib -ldl -lm $(LIBXML_LIBS) $(LIBPYTHON_LIBS) $(LIBARCHIVE_LIBS) $(LIBSQLITE_LIBS) \
+chrysalide0_LDFLAGS = $(TOOLKIT_LIBS) -L/usr/X11R6/lib -ldl -lm $(LIBXML_LIBS) $(LIBPYTHON_LIBS) $(LIBARCHIVE_LIBS) $(LIBSQLITE_LIBS) \
-L.libs -lchrysacore
-chrysalide_LDADD = $(LIBINTL)
+chrysalide0_LDADD = $(LIBINTL)
-EXTRA_framework_DEPENDENCIES = libchrysacore4.la libchrysacoreui.la
+EXTRA_chrysalide_DEPENDENCIES = libchrysacore4.la libchrysacoreui.la
-framework_SOURCES = \
- framework.h framework.c
+chrysalide_SOURCES = \
+ app.h app.c
-framework_CFLAGS = $(TOOLKIT4_CFLAGS)
+chrysalide_CFLAGS = $(TOOLKIT4_CFLAGS) $(LIBGIOUNIX_CFLAGS)
-framework_LDFLAGS = $(TOOLKIT4_LIBS) \
+chrysalide_LDFLAGS = $(TOOLKIT4_LIBS) $(LIBGIOUNIX_LIBS) \
-L.libs -lchrysacore4 -lchrysacoreui
-framework_LDADD =
+chrysalide_LDADD =
@@ -181,4 +196,4 @@ rost_LDFLAGS = $(LIBGOBJ_LIBS) -L.libs -lchrysacore
#SUBDIRS = core glibext $(GTKEXT_SUBDIR) analysis arch format common debug $(GUI_SUBDIR) mangling plugins schemas
-SUBDIRS = analysis arch common core glibext gtkext gui plugins
+SUBDIRS = analysis arch common core data format glibext gtkext gui plugins schemas
diff --git a/src/analysis/contents/encapsulated.c b/src/analysis/contents/encapsulated.c
index 451c340..22b61c0 100644
--- a/src/analysis/contents/encapsulated.c
+++ b/src/analysis/contents/encapsulated.c
@@ -30,8 +30,8 @@
#include "encapsulated-int.h"
#include "../db/misc/rlestr.h"
-#include "../storage/serialize-int.h"
#include "../../common/extstr.h"
+#include "../../glibext/serialize-int.h"
diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c
index 791f8b6..125016c 100644
--- a/src/analysis/contents/file.c
+++ b/src/analysis/contents/file.c
@@ -35,8 +35,8 @@
#include "file-int.h"
#include "../db/misc/rlestr.h"
-#include "../storage/serialize-int.h"
#include "../../core/logs.h"
+#include "../../glibext/serialize-int.h"
diff --git a/src/analysis/contents/memory.c b/src/analysis/contents/memory.c
index f7d2bd0..c6ccb5b 100644
--- a/src/analysis/contents/memory.c
+++ b/src/analysis/contents/memory.c
@@ -34,11 +34,10 @@
#include "memory-int.h"
-#include "../content-int.h"
#include "../db/misc/rlestr.h"
-#include "../storage/serialize-int.h"
#include "../../common/extstr.h"
#include "../../core/logs.h"
+#include "../../glibext/serialize-int.h"
@@ -337,6 +336,7 @@ bool g_memory_content_create(GMemoryContent *content, const bin_t *data, phys_t
if (allocated == NULL)
{
LOG_ERROR_N("malloc");
+ result = false;
goto exit;
}
diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c
index 95f513b..6f091ae 100644
--- a/src/analysis/contents/restricted.c
+++ b/src/analysis/contents/restricted.c
@@ -30,9 +30,9 @@
#include "restricted-int.h"
#include "../db/misc/rlestr.h"
-#include "../storage/serialize-int.h"
#include "../../common/extstr.h"
#include "../../core/logs.h"
+#include "../../glibext/serialize-int.h"
diff --git a/src/analysis/scan/patterns/backends/Makefile.am b/src/analysis/scan/patterns/backends/Makefile.am
index 23b0163..84711a7 100644
--- a/src/analysis/scan/patterns/backends/Makefile.am
+++ b/src/analysis/scan/patterns/backends/Makefile.am
@@ -6,10 +6,16 @@ libanalysisscanpatternsbackends_la_SOURCES = \
acism-int.h \
acism.h acism.c \
bitap-int.h \
- bitap.h bitap.c \
+ bitap.h bitap.c
+
+if BUILD_HS_SUPPORT
+
+libanalysisscanpatternsbackends_la_SOURCES += \
hyperscan-int.h \
hyperscan.h hyperscan.c
+endif
+
# Cf. https://www.gnu.org/software/automake/manual/html_node/Per_002dObject-Flags.html
AM_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBHS_CFLAGS)
diff --git a/src/analysis/storage/Makefile.am b/src/analysis/storage/Makefile.am
index 3eb287b..dad7411 100644
--- a/src/analysis/storage/Makefile.am
+++ b/src/analysis/storage/Makefile.am
@@ -6,12 +6,7 @@ libanalysisstorage_la_SOURCES = \
cache-int.h \
cache.h cache.c \
container-int.h \
- container.h container.c \
- serialize-int.h \
- serialize.h serialize.c \
- storage-int.h \
- storage.h storage.c \
- tpmem.h tpmem.c
+ container.h container.c
libanalysisstorage_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/analysis/storage/serialize.h b/src/analysis/storage/serialize.h
deleted file mode 100644
index 93a4496..0000000
--- a/src/analysis/storage/serialize.h
+++ /dev/null
@@ -1,64 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * serialize.h - prototypes pour les objets entreposables dans un cache
- *
- * Copyright (C) 2020 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_STORAGE_SERIALIZE_H
-#define _ANALYSIS_STORAGE_SERIALIZE_H
-
-
-#include <glib-object.h>
-
-
-#include "../../common/packed.h"
-
-
-
-#define G_TYPE_SERIALIZABLE_OBJECT g_serializable_object_get_type()
-#define G_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObject))
-#define G_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface))
-#define G_IS_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SERIALIZABLE_OBJECT))
-#define G_IS_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SERIALIZABLE_OBJECT))
-#define G_SERIALIZABLE_OBJECT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface))
-
-
-/* Intermédiaire pour la mise en cache d'objet (coquille vide) */
-typedef struct _GSerializableObject GSerializableObject;
-
-/* Intermédiaire pour la mise en cache d'objet (interface) */
-typedef struct _GSerializableObjectIface GSerializableObjectIface;
-
-
-/* Détermine le type d'une interface pour la mise en cache d'objet. */
-GType g_serializable_object_get_type(void) G_GNUC_CONST;
-
-/* storage.h : définition d'une conservation d'objets construits */
-typedef struct _GObjectStorage GObjectStorage;
-
-/* Charge un objet depuis une mémoire tampon. */
-bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, packed_buffer_t *);
-
-/* Sauvegarde un objet dans une mémoire tampon. */
-bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, packed_buffer_t *);
-
-
-
-#endif /* _ANALYSIS_STORAGE_SERIALIZE_H */
diff --git a/src/analysis/storage/tpmem.h b/src/analysis/storage/tpmem.h
deleted file mode 100644
index 34cbde6..0000000
--- a/src/analysis/storage/tpmem.h
+++ /dev/null
@@ -1,70 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * tpmem.h - prototypes pour la mémorisation des types d'objets mis en cache
- *
- * 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_STORAGE_TPMEM_H
-#define _ANALYSIS_STORAGE_TPMEM_H
-
-
-#include <glib-object.h>
-
-
-#include "../../common/packed.h"
-
-
-
-#define G_TYPE_TYPE_MEMORY g_type_memory_get_type()
-#define G_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TYPE_MEMORY, GTypeMemory))
-#define G_IS_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TYPE_MEMORY))
-#define G_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TYPE_MEMORY, GTypeMemoryClass))
-#define G_IS_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TYPE_MEMORY))
-#define G_TYPE_MEMORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TYPE_MEMORY, GTypeMemoryClass))
-
-
-/* Définition d'une mémoire de types d'objets (instance) */
-typedef struct _GTypeMemory GTypeMemory;
-
-/* Définition d'une mémoire de types d'objets (classe) */
-typedef struct _GTypeMemoryClass GTypeMemoryClass;
-
-
-/* Indique le type défini pour une mémoire de types d'objets. */
-GType g_type_memory_get_type(void);
-
-/* Crée une mémoire pour types d'objets. */
-GTypeMemory *g_type_memory_new(void);
-
-/* Apprend tous les types mémorisés dans un tampon. */
-bool g_type_memory_load_types(GTypeMemory *, packed_buffer_t *);
-
-/* Crée une nouvelle instance d'objet à partir de son type. */
-GObject *g_type_memory_create_object(GTypeMemory *, packed_buffer_t *);
-
-/* Sauvegarde le type d'un objet instancié. */
-bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, packed_buffer_t *);
-
-/* Enregistre tous les types mémorisés dans un tampon. */
-bool g_type_memory_store_types(GTypeMemory *, packed_buffer_t *);
-
-
-
-#endif /* _ANALYSIS_STORAGE_TPMEM_H */
diff --git a/src/framework.c b/src/app.c
index 96c97c3..ef62135 100644
--- a/src/framework.c
+++ b/src/app.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * framework.c - fichier d'entrée du programme
+ * app.c - fichier d'entrée du programme
*
* Copyright (C) 2024 Cyrille Bagard
*
@@ -22,15 +22,24 @@
*/
+#include <assert.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <string.h>
+#include <gio/gdesktopappinfo.h>
+#include <gio/gio.h>
+#include <sys/auxv.h>
-#include <gtk/gtk.h>
-
-#include "framework.h"
-#include "glibext/helpers.h"
+#include "app.h"
+#include "common/io.h"
+#include "common/xdg.h"
+#include "core/core.h"
+#include "core/logs.h"
#include "gui/core/core.h"
-#include "analysis/contents/file.h" // REMME
-#include "gtkext/hexview.h" // REMME
+#include "gui/window.h"
+#include "plugins/pglist.h"
@@ -42,8 +51,6 @@ struct _GtkChrysalideFramework
{
GtkApplication parent; /* A laisser en premier */
- GSettings *settings; /* Paramètres globaux */
-
GtkApplicationWindow *main_window; /* Fenêtre principale */
};
@@ -78,6 +85,20 @@ static void gtk_chrysalide_framework_activate(GApplication *);
+/* ---------------------- POINT D'ENTREE PRINCIPAL D'EXECUTION ---------------------- */
+
+
+/* Affiche des indications quant à l'utilisation du programme. */
+static void show_chrysalide_help(const char *);
+
+/* Affiche des indications sur la version courante du programme. */
+static void show_chrysalide_version(void);
+
+/* Installe au besoin une définition locale pour le système. */
+static void ensure_wm_icon_and_name(void);
+
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION D'APPLICATION PERSONNALISEE */
/* ---------------------------------------------------------------------------------- */
@@ -131,8 +152,6 @@ static void gtk_chrysalide_framework_class_init(GtkChrysalideFrameworkClass *kla
static void gtk_chrysalide_framework_init(GtkChrysalideFramework *app)
{
- app->settings = NULL;
-
app->main_window = NULL;
}
@@ -152,8 +171,6 @@ static void gtk_chrysalide_framework_init(GtkChrysalideFramework *app)
static void gtk_chrysalide_framework_dispose(GtkChrysalideFramework *app)
{
- g_clear_object(&app->settings);
-
g_clear_object(&app->main_window);
G_OBJECT_CLASS(gtk_chrysalide_framework_parent_class)->dispose(G_OBJECT(app));
@@ -197,7 +214,7 @@ GtkChrysalideFramework *gtk_chrysalide_framework_new(void)
GtkChrysalideFramework *result; /* Instance à retourner */
result = g_object_new(GTK_TYPE_CHRYSALIDE_FRAMEWORK,
- "application-id", "re.chrysalide.framework",
+ "application-id", FRAMEWORK_WINDOW_ID,
"flags", G_APPLICATION_DEFAULT_FLAGS,
NULL);
@@ -227,104 +244,183 @@ GtkChrysalideFramework *gtk_chrysalide_framework_new(void)
static void gtk_chrysalide_framework_activate(GApplication *app)
{
GtkChrysalideFramework *real_app; /* Version réelle de l'instance*/
- GSettings *settings; /* Paramètres globaux */
- GtkWindow *window; /* Fenêtre mise en place */
- GtkCssProvider *css; /* Feuille de style maison */
real_app = GTK_CHRYSALIDE_FRAMEWORK(app);
- /* Paramètres globaux */
+ real_app->main_window = gtk_framework_window_new(GTK_APPLICATION(app));
+ g_object_ref(G_OBJECT(real_app->main_window));
+
+ gtk_window_present(GTK_WINDOW(real_app->main_window));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* POINT D'ENTREE PRINCIPAL D'EXECUTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : name = nom du programme en question. *
+* *
+* Description : Affiche des indications quant à l'utilisation du programme. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- settings = g_settings_new("re.chrysalide.framework.mainapp");
- real_app->settings = settings;
+static void show_chrysalide_help(const char *name)
+{
+ char *tmp; /* Conservation modifiable */
+ char *base; /* Version courte du nom */
- /* Fenêtre principale */
+ tmp = strdup(name);
- window = GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(app)));
+ base = basename(tmp);
- real_app->main_window = GTK_APPLICATION_WINDOW(window);
- g_object_ref(G_OBJECT(window));
+ printf("\n");
- g_settings_bind(settings, "window-width", G_OBJECT(window), "default-width", G_SETTINGS_BIND_DEFAULT);
- g_settings_bind(settings, "window-height", G_OBJECT(window), "default-height", G_SETTINGS_BIND_DEFAULT);
- g_settings_bind(settings, "window-maximized", G_OBJECT(window), "maximized", G_SETTINGS_BIND_DEFAULT);
+ printf("Usage: %s [--help] [--version]\n", base);
+ printf(" %s [args] <filename(s)...>\n", base);
- gtk_window_set_title(window, "Chrysalide");
- gtk_window_present(window);
+ free(tmp);
+ printf("\n");
- do
- {
- GBinContent *cnt;
+ printf("\t-h --help\t\tShow this help message.\n");
+ printf("\t-v --version\t\tDisplay the program version.\n");
- GtkWidget *parent;
- GtkHexView *wgt;
+ printf("\n");
+ printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT);
-#if 0
+ printf("\n");
- cnt = g_file_content_new("tmp.bin");
+}
- parent = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
- gtk_box_set_homogeneous(GTK_BOX(parent), FALSE);
- gtk_window_set_child(window, parent);
- wgt = gtk_hex_view_new(cnt);
- gtk_box_append(GTK_BOX(parent), GTK_WIDGET(wgt));
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Affiche des indications sur la version courante du programme.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- wgt = gtk_hex_view_new(cnt);
- gtk_box_append(GTK_BOX(parent), GTK_WIDGET(wgt));
+static void show_chrysalide_version(void)
+{
+ printf("\n");
-#else
+ printf("-o- Chrysalide r%u -o-\n", REVISION);
+ printf(_("Compiled on %s at %s\n"), __DATE__, __TIME__);
- cnt = g_file_content_new("/bin/id");
- //cnt = g_file_content_new("tmp.bin");
+ printf("\n");
+}
- parent = gtk_scrolled_window_new();
- gtk_window_set_child(window, parent);
- wgt = gtk_hex_view_new(cnt);
- gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(parent), GTK_WIDGET(wgt));
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Installe au besoin une définition locale pour le système. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-#endif
+static void ensure_wm_icon_and_name(void)
+{
+ GDesktopAppInfo *info; /* Information du système */
+ GKeyFile *kfile; /* Définition d'application */
+ unsigned long exec_path; /* Chemin du programme */
+ char *filename; /* Nom de fichier à écrire */
+ GBytes *res; /* Données brutes d'une image */
+ gsize size; /* Taille de ces données */
+ gconstpointer data; /* Pointeur vers les données */
+ int fd; /* Flux ouvert en écriture */
+ /* Evaluation du besoin */
+ info = g_desktop_app_info_new(FRAMEWORK_WINDOW_ID ".desktop");
+ /**
+ * Si l'exécutable n'est pas valide (inconnu de $PATH),
+ * la variable info n'est pas initialisée.
+ */
+ if (info != NULL)
+ {
+ unref_object(info);
+ goto done;
}
- while (0);
+ /* Mise en place d'une définition d'application */
- /* Chargement des extensions de thème */
+ exec_path = getauxval(AT_EXECFN);
+ assert(exec_path != 0);
- /*
- css = gtk_css_provider_new();
+ kfile = g_key_file_new();
- gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/glibext/linestyle.css");
+ g_key_file_set_string(kfile, "Desktop Entry", "Name", "Chrysalide");
+ g_key_file_set_string(kfile, "Desktop Entry", "Comment[fr]", "Cadriciel de rétronception ciblant principalement les systèmes embarqués");
+ g_key_file_set_string(kfile, "Desktop Entry", "Comment", "Reverse Engineering Framework focused on embedded systems");
+ g_key_file_set_string(kfile, "Desktop Entry", "Type", "Application");
+ g_key_file_set_string(kfile, "Desktop Entry", "Exec", (const char *)exec_path);
+ g_key_file_set_string(kfile, "Desktop Entry", "Icon", "chrysalide-logo");
+ g_key_file_set_string(kfile, "Desktop Entry", "StartupNotify", "true");
+ g_key_file_set_string(kfile, "Desktop Entry", "MimeType", "application/vnd.android.package-archive");
- gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)),
- GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ filename = get_xdg_data_dir("applications/re.chrysalide.framework.gui.desktop", true);
- unref_object(css);
- */
+ g_key_file_save_to_file(kfile, filename, NULL);
- css = gtk_css_provider_new();
+ free(filename);
- gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gtkext/hexview.css");
+ g_key_file_free(kfile);
- gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)),
- GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ /* Ecriture de l'image */
- unref_object(css);
+ res = g_resources_lookup_data("/re/chrysalide/framework/images/chrysalide-logo.svg",
+ G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ assert(res != NULL);
-}
+ data = g_bytes_get_data(res, &size);
+ filename = get_xdg_data_dir("icons/hicolor/scalable/apps/chrysalide-logo.svg", true);
+ fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
-/* ---------------------------------------------------------------------------------- */
-/* POINT D'ENTREE PRINCIPAL D'EXECUTION */
-/* ---------------------------------------------------------------------------------- */
+ if (fd == -1)
+ LOG_ERROR_N("open");
+
+ else
+ {
+ safe_write(fd, data, size);
+ close(fd);
+ }
+
+ free(filename);
+
+ g_bytes_unref(res);
+
+ /* Sortie */
+
+ done:
+
+ ;
+
+}
/******************************************************************************
@@ -343,18 +439,125 @@ static void gtk_chrysalide_framework_activate(GApplication *app)
int main(int argc, char **argv)
{
int result; /* Bilan de l'exécution */
+ bool show_help; /* Affichage de l'aide ? */
+ bool show_version; /* Affichage de la version ? */
+ LogMessageType verbosity; /* Niveau de filtre de message */
+ int index; /* Indice d'argument */
+ int ret; /* Bilan d'un appel */
GtkChrysalideFramework *app; /* Gestion d'application GTK */
- if (!load_gui_components(AGC_BUFFER_FEATURES))
- return EXIT_FAILURE;
+ static struct option long_options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "verbosity", required_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+
+ result = EXIT_FAILURE;
+
+ /* Décodage des options */
+
+ show_help = false;
+ show_version = false;
+
+ verbosity = LMT_COUNT;
+
+ while (true)
+ {
+ ret = getopt_long(argc, argv, "hvV:", long_options, &index);
+ if (ret == -1) break;
+
+ switch (ret)
+ {
+ case 'h':
+ show_help = true;
+ break;
+
+ case 'v':
+ show_version = true;
+ break;
+
+ case 'V':
+ verbosity = strtoul(optarg, NULL, 10);
+ break;
+
+ }
+
+ }
+
+ /* Actions de base */
+
+ if (show_help)
+ {
+ show_chrysalide_help(argv[0]);
+ result = EXIT_SUCCESS;
+ goto exit;
+ }
+
+ if (show_version)
+ {
+ show_chrysalide_version();
+ result = EXIT_SUCCESS;
+ goto exit;
+ }
+
+ /* Lancement des choses sérieuses */
+
+ set_log_verbosity(verbosity);
+
+ /**
+ * Même s'il est dit que l'usage de GtkApplication permet de s'affranchir
+ * d'un appel à gtk_init(), il se trouve que la journalisation en mode
+ * graphique peut solliciter le panneau en GTK pour afficher des messages
+ * avant la mise en place de l'applicatif GTK principal :
+ *
+ * #2 0x00007ffff7b33403 in gtk_css_lookup_resolve (lookup=lookup@entry=0x7fffffff88a0, provider=provider@entry=0x0, sstyle=sstyle@entry=0x7fffe800a730, parent_style=parent_style@entry=0x0) at ../gtk/gtkcssstaticstyle.c:911
+ * #3 0x00007ffff7b3389f in gtk_css_static_style_new_compute (provider=0x0, filter=filter@entry=0x7fffffff8ea0, node=node@entry=0x0, change=<optimized out>, change@entry=0) at ../gtk/gtkcssstaticstyle.c:1026
+ * #4 0x00007ffff7b3392c in gtk_css_static_style_get_default () at ../gtk/gtkcssstaticstyle.c:711
+ * #5 0x00007ffff7b24b09 in gtk_css_node_init (cssnode=0x7fffe800a5b0) at ../gtk/gtkcssnode.c:641
+ * #6 0x00007ffff75d8dab in g_type_create_instance () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
+ * [...]
+ * #10 0x00007ffff7b3b8fa in gtk_css_widget_node_new (widget=widget@entry=0x5555555bf1b0) at ../gtk/gtkcsswidgetnode.c:160
+ * #11 0x00007ffff7ae4576 in gtk_widget_init (instance=<optimized out>, g_class=0x5555555be380) at ../gtk/gtkwidget.c:2345
+ * [...]
+ * #16 0x00007ffff73fd3f4 in get_framework_panel_singleton (...) at panels.c:329
+ * #17 0x00007ffff73fce35 in do_log_message_alt (...) at logs.c:56
+ * [...]
+ * #23 0x00007ffff74566db in init_all_plugins (load=true) at pglist.c:103
+ * #24 0x0000555555556d44 in main (argc=2, argv=0x7fffffffb568) at app.c:514
+ *
+ * L'initialisation permettant un retour de gtk_settings_get_default() non
+ * nul est ainsi forcée au plus tôt avec un appel à gtk_init() manuel.
+ */
+ gtk_init();
+
+ if (!load_core_components(ACC_GLOBAL_VARS))
+ goto exit;
+
+ if (!load_gui_components(AGC_BUFFER_FEATURES | AGC_PANELS))
+ goto exit_with_core;
+
+ init_all_plugins(true);
+
+ ensure_wm_icon_and_name();
+
+ g_set_prgname("Chrysalide");
app = gtk_chrysalide_framework_new();
- result = g_application_run(G_APPLICATION(app), argc, argv);
+ result = g_application_run(G_APPLICATION(app), 0, NULL);
g_object_unref(G_OBJECT(app));
- unload_gui_components(AGC_BUFFER_FEATURES);
+ exit_all_plugins();
+
+ unload_gui_components(AGC_BUFFER_FEATURES | AGC_PANELS);
+
+ exit_with_core:
+
+ unload_core_components(ACC_GLOBAL_VARS);
+
+ exit:
return result;
diff --git a/src/app.h b/src/app.h
new file mode 100644
index 0000000..645fa6b
--- /dev/null
+++ b/src/app.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * app.h - prototypes pour le fichier d'entrée du programme
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _APP_H
+#define _APP_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "glibext/helpers.h"
+
+
+
+/* --------------------- DEFINITION D'APPLICATION PERSONNALISEE --------------------- */
+
+
+#define GTK_TYPE_CHRYSALIDE_FRAMEWORK (gtk_chrysalide_framework_get_type())
+
+DECLARE_GTYPE(GtkChrysalideFramework, gtk_chrysalide_framework, GTK, CHRYSALIDE_FRAMEWORK);
+
+
+/* Crée une nouvelle application principale pour Chrysalide. */
+GtkChrysalideFramework *gtk_chrysalide_framework_new(void);
+
+
+
+/* ---------------------- POINT D'ENTREE PRINCIPAL D'EXECUTION ---------------------- */
+
+
+/* Point d'entrée du programme. */
+int main(int, char **);
+
+
+
+#endif /* _APP_H */
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
index 6ee2690..6683854 100644
--- a/src/arch/Makefile.am
+++ b/src/arch/Makefile.am
@@ -1,43 +1,57 @@
-noinst_LTLIBRARIES = libarch4.la # libarch.la
+noinst_LTLIBRARIES = libarch.la libarchui.la
+
+# libarch_la_SOURCES = \
+# archbase.h archbase.c \
+# context-int.h \
+# context.h context.c \
+# instriter.h instriter.c \
+# link.h link.c \
+# post.h post.c \
+# storage.h storage.c
+
+# libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+
+# libarch_la_LIBADD = \
+# operands/libarchoperands.la
+
+
+#
+# processor-int.h \
+# processor.h processor.c \
+#
libarch_la_SOURCES = \
- archbase.h archbase.c \
- context-int.h \
- context.h context.c \
- instriter.h instriter.c \
instruction-int.h \
instruction.h instruction.c \
- link.h link.c \
- operand-int.h operand-int.c \
+ operand-int.h \
operand.h operand.c \
- post.h post.c \
- processor-int.h \
- processor.h processor.c \
register-int.h \
register.h register.c \
- storage.h storage.c \
vmpa.h vmpa.c
-libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+libarch_la_CFLAGS = $(LIBGOBJ_CFLAGS)
libarch_la_LIBADD = \
instructions/libarchinstructions.la \
operands/libarchoperands.la
-libarch4_la_SOURCES = \
- vmpa.h vmpa.c
+libarchui_la_SOURCES = \
+ instruction-ui-int.h \
+ instruction-ui.h instruction-ui.c \
+ operand-ui-int.h \
+ operand-ui.h operand-ui.c
-libarch4_la_CFLAGS = $(TOOLKIT_CFLAGS)
+libarchui_la_CFLAGS = $(LIBGTK_CFLAGS)
-libarch4_la_LIBADD =
+libarchui_la_LIBADD = \
+ operands/libarchoperandsui.la
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
-dev_HEADERS = $(libarch_la_SOURCES:%c=)
-
+dev_HEADERS = $(libarch_la_SOURCES:%c=) $(libarchui_la_SOURCES:%c=)
-#SUBDIRS = instructions operands
+SUBDIRS = instructions operands
diff --git a/src/arch/archbase.h b/src/arch/archbase.h
index 59bf18e..b29d2a1 100644
--- a/src/arch/archbase.h
+++ b/src/arch/archbase.h
@@ -50,6 +50,7 @@ typedef uint64_t vmpa_t;
#define VMPA_MAX_SIZE 19
+#if 0
/* Taille des données intégrées */
typedef enum _MemoryDataSize
{
@@ -68,6 +69,7 @@ typedef enum _MemoryDataSize
MDS_64_BITS_SIGNED = 0x85 /* Opérande sur 64 bits signés */
} MemoryDataSize;
+#endif
#define MDS_RANGE(mds) ((mds & 0xf) - 1)
@@ -99,13 +101,13 @@ typedef enum _MemoryDataSize
__result; \
})
-
+#if 0
#define MDS_4_BITS MDS_4_BITS_UNSIGNED
#define MDS_8_BITS MDS_8_BITS_UNSIGNED
#define MDS_16_BITS MDS_16_BITS_UNSIGNED
#define MDS_32_BITS MDS_32_BITS_UNSIGNED
#define MDS_64_BITS MDS_64_BITS_UNSIGNED
-
+#endif
/* Etablit la comparaison entre deux adresses. */
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 7dbbe27..d426cea 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction-int.h - prototypes pour la définition générique interne des instructions
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,18 +25,29 @@
#define _ARCH_INSTRUCTION_INT_H
+#include <stdint.h>
+
+
#include "instruction.h"
-#include "../analysis/storage/storage.h"
#include "../common/array.h"
-#include "../glibext/objhole.h"
+#include "../glibext/objhole-int.h"
/* Indique l'encodage d'une instruction de façon détaillée. */
-typedef const char * (* get_instruction_encoding_fc) (const GArchInstruction *);
+typedef char * (* get_instruction_encoding_fc) (const GArchInstruction *);
/* Fournit le nom humain de l'instruction manipulée. */
-typedef const char * (* get_instruction_keyword_fc) (GArchInstruction * );
+typedef char * (* get_instruction_keyword_fc) (const GArchInstruction *);
+
+
+
+#if 0
+
+#include "../analysis/storage/storage.h"
+
+
+
/* Complète un désassemblage accompli pour une instruction. */
typedef void (* call_instruction_hook_fc) (GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
@@ -67,80 +78,45 @@ typedef bool (* store_instruction_fc) (GArchInstruction *, GObjectStorage *, pac
-/* Informations glissées dans la structure GObject de GArchOperand */
-typedef struct _instr_extra_data_t
-{
- itid_t uid; /* Identifiant unique du type */
-
- ArchInstrFlag flags; /* Informations complémentaires*/
-
-} instr_extra_data_t;
+#endif
-/* Informations glissées dans la structure GObject de GArchInstruction */
-typedef union _instr_obj_extra_t
-{
- instr_extra_data_t data; /* Données embarquées */
- lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */
-} instr_obj_extra_t;
+/* Conservation d'une adresse et de propriétées */
+typedef unsigned long compact_ins_link_t;
/* Définition générique d'une instruction d'architecture (instance) */
struct _GArchInstruction
{
- GObject parent; /* A laisser en premier */
+ GThickObject parent; /* A laisser en premier */
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+ GBinaryPortion *rel_area; /* Zone de référence */
+ rel_mrange_t rel_range; /* Emplacement compressé */
/**
- * L'inclusion des informations suivantes dépend de l'architecture.
- *
- * Si la structure GObject possède un trou, on remplit de préférence
- * ce dernier.
+ * A laisser à la suite de la localisation précédente pour éviter
+ * les espaces vide dans la structure.
*/
+ uint16_t link_count; /* Quantité de liens établis */
- instr_obj_extra_t extra; /* Externalisation embarquée */
-
-#endif
-
- mrange_t range; /* Emplacement en mémoire */
+ compact_ins_link_t *links; /* Liste de ces liens */
flat_array_t *operands; /* Liste des opérandes */
- /**
- * Il existe le besoin indéniable d'un verrou pour les accès aux instructions
- * liées. Il faut par ailleurs un verrou distinct pour les sources et les
- * destinations car une même instruction peut boucler sur elle même et la
- * fonction g_arch_instruction_change_link() pose des verrous sur les
- * deux extrémités.
- *
- * La GLib propose les fonctions g_bit_lock() / g_bit_unlock(), légères mais
- * sans distinction entre lectures et écritures. Tant pis : la réduction de
- * l'empreinte mémoire prime !
- *
- * Par contre la documentation indique :
- *
- * """
- * Attempting to lock on two different bits within the same integer is not supported.
- * """
- *
- * Donc on doit bien conserver un compteur distinct pour chaque extrémité.
- * Cela correspond de toute façon à la définition optimisée des tableaux
- * suivante.
- */
-
- flat_array_t *from; /* Origines des références */
- flat_array_t *to; /* Instructions visées */
-
};
/* Définition générique d'une instruction d'architecture (classe) */
struct _GArchInstructionClass
{
- GObjectClass parent; /* A laisser en premier */
+ GThickObjectClass parent; /* A laisser en premier */
get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */
get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */
+
+#if 0
+
+ //get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */
+ //get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */
call_instruction_hook_fc call_hook; /* Décrochages éventuels */
build_instruction_tooltip_fc build_tooltip; /* Construction d'une bulle*/
get_instruction_desc_fc get_desc; /* Description assez complète */
@@ -155,22 +131,50 @@ struct _GArchInstructionClass
//get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés */
+#endif
+
};
+/* Met en place une instruction d'architecture. */
+bool g_arch_instruction_create(GArchInstruction *, itid_t);
+
+
+
/**
* Accès aux informations éventuellement déportées.
*/
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
-# define GET_ARCH_INSTR_EXTRA(ins) (instr_extra_data_t *)&ins->extra
+#define ARCH_INSTRUCTION_EXTRA_DATA \
+ \
+ unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \
+ \
+ /** \
+ * itid_t \
+ */ \
+ unsigned int tid : 16; \
+ \
+ /** \
+ * ArchOperandFlag \
+ */ \
+ unsigned int flags : 8;
-#else
-# define GET_ARCH_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), instr_extra_data_t)
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _instruction_extra_data_t
+{
+ ARCH_INSTRUCTION_EXTRA_DATA; /* Socle commun */
+
+} instruction_extra_data_t;
+
+
+#define GET_ARCH_INSTR_EXTRA(op) \
+ GET_GOBJECT_EXTRA(op, instruction_extra_data_t)
+
+#define SET_ARCH_INSTR_EXTRA(op, data) \
+ SET_GOBJECT_EXTRA(op, instruction_extra_data_t, data)
-#endif
/**
diff --git a/src/arch/instruction-ui-int.h b/src/arch/instruction-ui-int.h
new file mode 100644
index 0000000..b07f40c
--- /dev/null
+++ b/src/arch/instruction-ui-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instruction-ui-int.h - prototypes pour la définition générique interne des instructions sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRUCTION_UI_INT_H
+#define _ARCH_INSTRUCTION_UI_INT_H
+
+
+#include "instruction-ui.h"
+
+
+
+#if 0
+
+/* Traduit un opérande en version humainement lisible. */
+typedef void (* print_operand_ui_fc) (const GArchOperandUI *, GBufferLine *);
+
+/* Construit un petit résumé concis de l'opérande. */
+typedef char * (* build_operand_ui_tooltip_fc) (const GArchOperandUI *, const GLoadedBinary *);
+
+
+
+/* Définition générique d'un opérande d'architecture (interface) */
+struct _GArchOperandUIInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ print_operand_ui_fc print; /* Texte humain équivalent */
+ build_operand_ui_tooltip_fc build_tooltip; /* Définition de description*/
+
+};
+
+#endif
+
+
+#endif /* _ARCH_INSTRUCTION_UI_INT_H */
diff --git a/src/arch/instruction-ui.c b/src/arch/instruction-ui.c
new file mode 100644
index 0000000..7f923d8
--- /dev/null
+++ b/src/arch/instruction-ui.c
@@ -0,0 +1,254 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instruction-ui.c - gestion générique des instructions sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "instruction-ui.h"
+
+
+#include "instruction-int.h"
+#include "operand-ui.h"
+#include "../analysis/content.h"
+#include "../common/cpp.h"
+#include "../glibext/generator-int.h"
+#include "../glibext/options/asm.h"
+
+
+
+/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+
+
+/* Renseigne sur les propriétés liées à un générateur. */
+static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *, size_t, size_t);
+
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_arch_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+#if 0
+
+/* Retrouve l'emplacement correspondant à une position donnée. */
+static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **);
+
+/* Détermine si le conteneur s'inscrit dans une plage donnée. */
+static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *);
+
+#endif
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OFFRE DE CAPACITES DE GENERATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface)
+{
+ /**
+ * La procédure par défaut de iface->count() ne doit pas être retouchée !
+ */
+
+ iface->get_flags = g_arch_instruction_ui_get_flags;
+ iface->populate = g_arch_instruction_ui_populate_line;
+
+#if 0
+ iface->compute = (linegen_compute_fc)g_arch_instruction_ui_compute_cursor;
+ iface->contain = (linegen_contain_fc)g_arch_instruction_ui_contain_cursor;
+#endif
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* *
+* Description : Renseigne sur les propriétés liées à un générateur. *
+* *
+* Retour : Propriétés particulières associées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *generator, size_t index, size_t repeat)
+{
+ BufferLineFlags result; /* Fanions à retourner */
+
+ result = BLF_HAS_CODE;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à utiliser pour l'impression. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* line = ligne de rendu à compléter. *
+* data = éventuelle donnée complémentaire fournie. *
+* *
+* Description : Etablit dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+ GArchInstruction *instr; /* Version spécialisée */
+ GBinContent *content; /* Contenu brut d'origine */
+ mrange_t range; /* Emplacement couvert */
+ char *key; /* Mot clef principal */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+
+ instr = G_ARCH_INSTRUCTION(generator);
+ content = G_BIN_CONTENT(data);
+
+ /* Prologue */
+
+ if (g_arch_instruction_get_range(instr, &range))
+ {
+ g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL);
+
+ }
+
+ /* Instruction proprement dite */
+
+ key = g_arch_instruction_get_keyword(instr);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr));
+
+ free(key);
+
+ /* Liste des opérandes */
+
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ count = g_arch_instruction_count_operands(instr);
+
+ if (count > 0)
+ {
+ op = g_arch_instruction_get_operand(instr, 0);
+ g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line);
+ unref_object(op);
+
+ for (i = 1; i < count; i++)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_NONE, STCSL(" "), NULL, NULL);
+
+ op = g_arch_instruction_get_operand(instr, i);
+ g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line);
+ unref_object(op);
+
+ }
+
+ }
+
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+
+}
+
+
+#if 0
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = générateur à consulter. *
+* x = position géographique sur la ligne concernée. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* cursor = emplacement à constituer. [OUT] *
+* *
+* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor)
+{
+ *cursor = g_binary_cursor_new();
+
+ g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = générateur à consulter. *
+* index = indice de cette même ligne dans le tampon global. *
+* repeat = indice d'utilisations successives du générateur. *
+* cursor = emplacement à analyser. *
+* *
+* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
+* *
+* Retour : Bilan de la détermination, utilisable en comparaisons. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor)
+{
+ int result; /* Conclusion à retourner */
+ vmpa2t addr; /* Autre emplacement à comparer*/
+
+ assert(G_IS_BINARY_CURSOR(cursor));
+
+ g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr);
+
+ result = cmp_mrange_with_vmpa(&instr->range, &addr);
+
+ return result;
+
+}
+
+
+#endif
diff --git a/src/arch/instruction-ui.h b/src/arch/instruction-ui.h
new file mode 100644
index 0000000..62a52f2
--- /dev/null
+++ b/src/arch/instruction-ui.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instruction-ui.h - prototypes pour la gestion générique des instructions sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRUCTION_UI_H
+#define _ARCH_INSTRUCTION_UI_H
+
+
+#include "../glibext/generator.h"
+#include "../glibext/helpers.h"
+
+
+
+/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *);
+
+
+
+#endif /* _ARCH_INSTRUCTION_UI_H */
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index cd1e9c7..36bdecb 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction.c - gestion générique des instructions
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,102 +26,93 @@
#include <assert.h>
#include <malloc.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <limits.h>
#include <string.h>
#include "instruction-int.h"
-#include "storage.h"
-#include "../analysis/storage/serialize-int.h"
-#include "../core/columns.h"
+#include "../common/leb128.h"
#include "../core/logs.h"
#include "../core/processors.h"
-#include "../glibext/gbinarycursor.h"
-#include "../glibext/linegen-int.h"
+#include "../glibext/serialize-int.h"
-/* Initialise la classe générique des instructions. */
-static void g_arch_instruction_class_init(GArchInstructionClass *);
-
-/* Initialise une instance d'opérande d'architecture. */
-static void g_arch_instruction_init(GArchInstruction *);
-/* Procède à l'initialisation de l'interface de génération. */
-static void g_arch_instruction_generator_init(GLineGeneratorInterface *);
-/* Procède à l'initialisation de l'interface de sérialisation. */
-static void g_arch_instruction_serializable_init(GSerializableObjectInterface *);
-
-/* Supprime toutes les références externes. */
-static void g_arch_instruction_dispose(GArchInstruction *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_arch_instruction_finalize(GArchInstruction *);
+/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */
+/* Initialise la classe générique des instructions. */
+static void g_arch_instruction_class_init(GArchInstructionClass *);
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_arch_instruction_load_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Initialise une instance d'opérande d'architecture. */
+static void g_arch_instruction_init(GArchInstruction *);
-/* Sauvegarde toutes les destinations d'une instruction. */
-bool g_arch_instruction_store_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Supprime toutes les références externes. */
+static void g_arch_instruction_dispose(GObject *);
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_instruction_finalize(GObject *);
+/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
-/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
+#define COMPACT_INS_LINK_MASK_DIR (1ul << (__WORDSIZE - 1))
+#define COMPACT_INS_LINK_MASK_TYPE 0xf
+#define COMPACT_INS_LINK_MASK (COMPACT_INS_LINK_MASK_DIR | COMPACT_INS_LINK_MASK_TYPE)
-/* Indique le nombre de ligne prêtes à être générées. */
-static size_t g_arch_instruction_count_lines(const GArchInstruction *);
+#define COMPACT_INS_LINK_FROM (0ul << (__WORDSIZE - 1))
+#define COMPACT_INS_LINK_TO (1ul << (__WORDSIZE - 1))
-#ifdef INCLUDE_GTK_SUPPORT
+#define COMPACT_INS_LINK_DIR(cl) (cl & COMPACT_INS_LINK_MASK_DIR)
+#define COMPACT_INS_LINK_PTR(cl) ((GArchInstruction *)(cl & ~COMPACT_INS_LINK_MASK))
+#define COMPACT_INS_LINK_TYPE(cl) (cl & COMPACT_INS_LINK_MASK_TYPE)
-/* Retrouve l'emplacement correspondant à une position donnée. */
-static void g_arch_instruction_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **);
+#define MAKE_COMPACT_INS_LINK(d, i, t) \
+ (compact_ins_link_t)(d | (unsigned long)i | t)
-/* Détermine si le conteneur s'inscrit dans une plage donnée. */
-static int g_arch_instruction_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *);
+/* Détermine si un type de lien existe dans une instruction. */
+static bool _g_arch_instruction_has_link(const GArchInstruction *, compact_ins_link_t, InstructionLinkType);
-#endif
+/* Détermine si un lien existe entre deux instructions. */
+static bool _g_arch_instruction_has_link_with(const GArchInstruction *, compact_ins_link_t, const GArchInstruction *);
-/* Renseigne sur les propriétés liées à un générateur. */
-static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *, size_t, size_t);
+/* Fournit la quantité d'instructions pointant vers une autre. */
+static size_t _g_arch_instruction_count_links(const GArchInstruction *, compact_ins_link_t);
-/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
-static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
+/* Fournit les détails d'un lien donné avec une instruction. */
+static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *, size_t, compact_ins_link_t, InstructionLinkType *);
-/* Imprime dans une ligne de rendu le contenu représenté. */
-static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
-/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
-/* Charge un contenu depuis une mémoire tampon. */
-static bool _g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Charge un objet depuis un flux de données. */
+static bool g_arch_instruction_load(GSerializableObject *, GObjectStorage *, int);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Sauvegarde un objet dans un flux de données. */
+static bool g_arch_instruction_store(const GSerializableObject *, GObjectStorage *, int);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool _g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION GENERIQUE D'INSTRUCTION */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour une instruction d'architecture. */
-G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_init)
- G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_init));
+G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_THICK_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_object_iface_init)
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_arch_instruction_ui_token_generator_iface_init));
+
/******************************************************************************
@@ -139,28 +130,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
static void g_arch_instruction_class_init(GArchInstructionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchInstructionClass *instr; /* Encore une autre vision... */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_arch_instruction_finalize;
-
- instr = G_ARCH_INSTRUCTION_CLASS(klass);
-
- instr->print = (print_instruction_fc)_g_arch_instruction_print;
-
- instr->load = (load_instruction_fc)_g_arch_instruction_load;
- instr->store = (store_instruction_fc)_g_arch_instruction_store;
+ object->dispose = g_arch_instruction_dispose;
+ object->finalize = g_arch_instruction_finalize;
}
/******************************************************************************
* *
-* Paramètres : instr = instance à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Initialise une instance d'instruction d'architecture. *
+* Description : Procède à l'initialisation de l'interface de sérialisation. *
* *
* Retour : - *
* *
@@ -168,27 +151,19 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass)
* *
******************************************************************************/
-static void g_arch_instruction_init(GArchInstruction *instr)
+static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *iface)
{
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- INIT_GOBJECT_EXTRA_LOCK(extra);
-
- instr->operands = NULL;
-
- instr->from = NULL;
- instr->to = NULL;
+ iface->load = g_arch_instruction_load;
+ iface->store = g_arch_instruction_store;
}
/******************************************************************************
* *
-* Paramètres : iface = interface GLib à initialiser. *
+* Paramètres : instr = instance à initialiser. *
* *
-* Description : Procède à l'initialisation de l'interface de génération. *
+* Description : Initialise une instance d'instruction d'architecture. *
* *
* Retour : - *
* *
@@ -196,42 +171,22 @@ static void g_arch_instruction_init(GArchInstruction *instr)
* *
******************************************************************************/
-static void g_arch_instruction_generator_init(GLineGeneratorInterface *iface)
+static void g_arch_instruction_init(GArchInstruction *instr)
{
- iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines;
-#ifdef INCLUDE_GTK_SUPPORT
- iface->compute = (linegen_compute_fc)g_arch_instruction_compute_cursor;
- iface->contain = (linegen_contain_fc)g_arch_instruction_contain_cursor;
-#endif
- iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2;
- iface->print = (linegen_print_fc)g_arch_instruction_print;
-
-}
+ instr->rel_area = NULL;
+ instr->link_count = 0;
-/******************************************************************************
-* *
-* Paramètres : iface = interface GLib à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'interface de sérialisation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ instr->links = NULL;
-static void g_arch_instruction_serializable_init(GSerializableObjectInterface *iface)
-{
- iface->load = (load_serializable_object_cb)g_arch_instruction_load;
- iface->store = (store_serializable_object_cb)g_arch_instruction_store;
+ instr->operands = NULL;
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -241,43 +196,38 @@ static void g_arch_instruction_serializable_init(GSerializableObjectInterface *i
* *
******************************************************************************/
-static void g_arch_instruction_dispose(GArchInstruction *instr)
+static void g_arch_instruction_dispose(GObject *object)
{
+ GArchInstruction *instr; /* Version spécialisée */
size_t count; /* Nombre d'opérandes en place */
size_t i; /* Boucle de parcours */
GArchOperand *op; /* Opérande à manipuler */
- g_arch_instruction_lock_operands(instr);
+ instr = G_ARCH_INSTRUCTION(object);
+
+ g_clear_object(&instr->rel_area);
+
+ g_arch_instruction_delete_all_links(instr);
- count = _g_arch_instruction_count_operands(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ count = g_arch_instruction_count_operands(instr);
for (i = 0; i < count; i++)
{
- op = _g_arch_instruction_get_operand(instr, 0);
+ op = g_arch_instruction_get_operand(instr, 0);
rem_item_from_flat_array(&instr->operands, 0, sizeof(GArchOperand *));
/**
* Une fois pour l'obtention, une autre pour la libération !
*/
- g_object_unref(G_OBJECT(op));
- g_object_unref(G_OBJECT(op));
+ unref_object(op);
+ unref_object(op);
}
- g_arch_instruction_unlock_operands(instr);
-
-#ifndef NDEBUG
- g_arch_instruction_lock_src(instr);
- assert(count_flat_array_items(instr->from) == 0);
- g_arch_instruction_unlock_src(instr);
-#endif
-
-#ifndef NDEBUG
- g_arch_instruction_lock_dest(instr);
- assert(count_flat_array_items(instr->to) == 0);
- g_arch_instruction_unlock_dest(instr);
-#endif
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
@@ -286,7 +236,7 @@ static void g_arch_instruction_dispose(GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -296,38 +246,26 @@ static void g_arch_instruction_dispose(GArchInstruction *instr)
* *
******************************************************************************/
-static void g_arch_instruction_finalize(GArchInstruction *instr)
+static void g_arch_instruction_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
+ GArchInstruction *instr; /* Version spécialisée */
-}
+ instr = G_ARCH_INSTRUCTION(object);
+ if (instr->links != NULL)
+ free(instr->links);
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* *
-* Description : Indique l'encodage d'une instruction de façon détaillée. *
-* *
-* Retour : Description humaine de l'encodage utilisé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-const char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
-{
- return G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_encoding(instr);
+ G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à modifier. *
-* flag = drapeau d'information complémentaire à planter. *
+* Paramètres : instr = instance à initialiser pleinement. *
+* tid = identifiant associé au type d'instructions ciblé. *
* *
-* Description : Ajoute une information complémentaire à une instruction. *
+* Description : Met en place une instruction d'architecture. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -335,22 +273,18 @@ const char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
* *
******************************************************************************/
-bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
+bool g_arch_instruction_create(GArchInstruction *instr, itid_t tid)
{
bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
- assert(flag <= AIF_HIGH_USER);
+ result = true;
extra = GET_ARCH_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = !(extra->flags & flag);
+ extra.tid = tid;
- extra->flags |= flag;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ SET_ARCH_INSTR_EXTRA(instr, &extra);
return result;
@@ -359,33 +293,24 @@ bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à modifier. *
-* flag = drapeau d'information complémentaire à planter. *
+* Paramètres : instr = instruction quelconque à consulter. *
* *
-* Description : Retire une information complémentaire à une instruction. *
+* Description : Fournit l'identifiant correspondant à un type d'instructions.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Identifiant unique par type d'instruction et architecture. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag)
+itid_t g_arch_instruction_get_type_id(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- assert(flag <= AIF_HIGH_USER);
+ itid_t result; /* Numéro à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
extra = GET_ARCH_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = (extra->flags & flag);
-
- extra->flags &= ~flag;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.tid;
return result;
@@ -395,30 +320,23 @@ bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag)
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à consulter. *
-* flag = drapeau d'information à rechercher. *
* *
-* Description : Détermine si une instruction possède un fanion particulier. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : Bilan de la détection. *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag flag)
+char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- assert(flag <= AIF_HIGH_USER);
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ char *result; /* Encodage à retourner */
+ GArchInstructionClass *class; /* Classe des instructions */
- result = (extra->flags & flag);
+ class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = class->get_encoding(instr);
return result;
@@ -427,28 +345,24 @@ bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag fl
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à modifier. *
+* Paramètres : instr = instruction d'assemblage à consulter. *
* *
-* Description : Fournit les informations complémentaires d'une instruction. *
+* Description : Fournit le nom humain de l'instruction manipulée. *
* *
-* Retour : Eventuels drapeaux d'information complémentaire à plantés. *
+* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
-ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
+char *g_arch_instruction_get_keyword(const GArchInstruction *instr)
{
- ArchInstrFlag result; /* Fanions à retourner */
- instr_extra_data_t *extra; /* Données insérées à modifier */
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ char *result; /* Etiquette à retourner */
+ GArchInstructionClass *class; /* Classe des instructions */
- result = extra->flags;
+ class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = class->get_keyword(instr);
return result;
@@ -457,10 +371,12 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* uid = identifiant unique par type d'instruction. *
+* Paramètres : instr = instruction quelconque à compléter. *
+* area = portion de binaire incluant l'instruction. *
+* start = adresse virtuelle et/ou position physique. *
+* length = taille de l'instruction. *
* *
-* Description : Définit l'identifiant unique pour un ensemble d'instructions.*
+* Description : Calcule la localisation d'une instruction. *
* *
* Retour : - *
* *
@@ -468,358 +384,214 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
* *
******************************************************************************/
-void g_arch_instruction_set_unique_id(GArchInstruction *instr, itid_t uid)
+void g_arch_instruction_compute_range(GArchInstruction *instr, GBinaryPortion *area, const vmpa2t *start, phys_t length)
{
- instr_extra_data_t *extra; /* Données insérées à modifier */
+ const mrange_t *a_range; /* Couverture de la portion */
+ phys_t diff; /* Décalage à appliquer */
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ a_range = g_binary_portion_get_range(area);
- extra->uid = uid;
+ assert(mrange_contains_addr(a_range, start));
- UNLOCK_GOBJECT_EXTRA(extra);
+ diff = compute_vmpa_diff(get_mrange_addr(a_range), start);
-}
+ instr->rel_area = area;
+ ref_object(area);
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* *
-* Description : Fournit l'identifiant unique pour un ensemble d'instructions.*
-* *
-* Retour : Identifiant unique par type d'instruction et architecture. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-itid_t g_arch_instruction_get_unique_id(const GArchInstruction *instr)
-{
- itid_t result; /* Numéro à retourner */
- instr_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->uid;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
+ init_rel_mrange(&instr->rel_range, diff, length);
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à traiter. *
-* type = type de procédure à utiliser. *
-* proc = représentation de l'architecture utilisée. *
-* context = contexte associé à la phase de désassemblage. *
-* format = accès aux données du binaire d'origine. *
+* Paramètres : instr = instruction quelconque à consulter. *
+* range = localisation de l'instruction. [OUT] *
* *
-* Description : Complète un désassemblage accompli pour une instruction. *
+* Description : Fournit la place mémoire d'une instruction. *
* *
-* Retour : - *
+* Retour : Validité de la localisation : existence d'une définition ? *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format)
+bool g_arch_instruction_get_range(const GArchInstruction *instr, mrange_t *range)
{
- GArchInstructionClass *class; /* Classe des instructions */
+ bool result; /* Statut à retourner */
+ const mrange_t *a_range; /* Couverture de la portion */
+ vmpa2t start; /* Position de départ complète */
- class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+ result = (instr->rel_area != NULL);
- if (class->call_hook != NULL)
- class->call_hook(instr, type, proc, context, format);
+ if (result)
+ {
+ a_range = g_binary_portion_get_range(instr->rel_area);
-}
+ copy_vmpa(&start, get_mrange_addr(a_range));
+ advance_vmpa(&start, get_rel_mrange_offset(&instr->rel_range));
+ init_mrange(range, &start, get_rel_mrange_length(&instr->rel_range));
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à modifier. *
-* address = adresse virtuelle et/ou position physique. *
-* length = taille de l'instruction. *
-* *
-* Description : Définit la localisation d'une instruction. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ }
-void g_arch_instruction_set_range(GArchInstruction *instr, const mrange_t *range)
-{
- copy_mrange(&instr->range, range);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
+* Paramètres : instr = instruction à venir modifier. *
+* flag = drapeau d'information complémentaire à planter. *
* *
-* Description : Fournit la place mémoire d'une instruction. *
+* Description : Ajoute une information complémentaire à une instruction. *
* *
-* Retour : Zone mémoire couverte par l'instruction. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-const mrange_t *g_arch_instruction_get_range(const GArchInstruction *instr)
+bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstructionFlag flag)
{
- return &instr->range;
+ bool result; /* Bilan à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
-}
+ assert(flag <= AIF_HIGH_USER);
+ extra = GET_ARCH_INSTR_EXTRA(instr);
+ result = !(extra.flags & flag);
-/******************************************************************************
-* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* offset = position physique dans le code binaire/NULL. [OUT] *
-* length = taille de l'instruction ou NULL. [OUT] *
-* address = adresse virtuelle ou position physique/NULL. [OUT] *
-* *
-* Description : Fournit la localisation d'une instruction. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ extra.flags |= flag;
-void g_arch_instruction_get_location(const GArchInstruction *instr, off_t *offset, off_t *length, vmpa_t *address)
-{
- //if (offset != NULL) *offset = instr->offset;
- //if (length != NULL) *length = instr->length;
+ SET_ARCH_INSTR_EXTRA(instr, &extra);
- //if (address != NULL) *address = instr->address;
+ return result;
}
-
/******************************************************************************
* *
-* Paramètres : instr = instruction à consulter. *
-* rregs = liste des rgistres lus. [OUT] *
-* rcount = nombre de registres lus. [OUT] *
-* wregs = liste des rgistres écrits. [OUT] *
-* wcount = nombre de registres écrits. [OUT] *
+* Paramètres : instr = instruction à venir modifier. *
+* flag = drapeau d'information complémentaire à planter. *
* *
-* Description : Liste les registres lus et écrits par l'instruction. *
+* Description : Retire une information complémentaire à une instruction. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
-* Remarques : Les compteurs de références sont à décrémenter après usage ! *
+* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount)
+bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstructionFlag flag)
{
-#if 0
+ bool result; /* Bilan à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
- size_t i; /* Boucle de parcours */
+ assert(flag <= AIF_HIGH_USER);
- *rregs = NULL;
- *rcount = 0;
- *wregs = NULL;
- *wcount = 0;
+ extra = GET_ARCH_INSTR_EXTRA(instr);
- instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
+ result = (extra.flags & flag);
- for (i = 0; i < *rcount; i++)
- g_object_ref(G_OBJECT((*rregs)[i]));
+ extra.flags &= ~flag;
- for (i = 0; i < *wcount; i++)
- g_object_ref(G_OBJECT((*wregs)[i]));
+ SET_ARCH_INSTR_EXTRA(instr, &extra);
-#endif
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* MANIPULATION DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction à mettre à jour. *
+* Paramètres : instr = instruction à venir consulter. *
+* flag = drapeau d'information à rechercher. *
* *
-* Description : Verrouille les accès à la liste des opérandes. *
+* Description : Détermine si une instruction possède un fanion particulier. *
* *
-* Retour : - *
+* Retour : Bilan de la détection. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_lock_operands(GArchInstruction *instr)
+bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstructionFlag flag)
{
- lock_flat_array(&instr->operands);
+ bool result; /* Bilan à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
-}
+ assert(flag <= AIF_HIGH_USER);
+ extra = GET_ARCH_INSTR_EXTRA(instr);
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à mettre à jour. *
-* *
-* Description : Déverrouille les accès à la liste des opérandes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result = (extra.flags & flag);
-void g_arch_instruction_unlock_operands(GArchInstruction *instr)
-{
- unlock_flat_array(&instr->operands);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* operand = instruction à venir associer. *
+* Paramètres : instr = instruction à venir consulter. *
* *
-* Description : Attache un opérande supplémentaire à une instruction. *
+* Description : Fournit les particularités de l'instruction. *
* *
-* Retour : - *
+* Retour : Somme de tous les fanions associés à l'opérande. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand)
+ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
{
- GSingletonFactory *factory; /* Unise à instances uniques */
- GArchOperand *singleton; /* Instance retenue */
-
- factory = get_operands_factory();
-
- singleton = G_ARCH_OPERAND(g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand)));
-
- g_object_unref(G_OBJECT(operand));
- g_object_unref(G_OBJECT(factory));
-
- g_arch_instruction_lock_operands(instr);
-
- add_item_to_flat_array(&instr->operands, &singleton, sizeof(GArchOperand *));
-
- g_arch_instruction_unlock_operands(instr);
+ ArchInstructionFlag result; /* Fanions à retourner */
+ instruction_extra_data_t extra; /* Données insérées à modifier */
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instance à consulter. *
-* *
-* Description : Indique la quantité d'opérandes présents dans l'instruction. *
-* *
-* Retour : Nombre d'opérandes attachés. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ extra = GET_ARCH_INSTR_EXTRA(instr);
-size_t _g_arch_instruction_count_operands(const GArchInstruction *instr)
-{
- size_t result; /* Décompte à retourner */
-
- result = count_flat_array_items(instr->operands);
+ result = extra.flags;
return result;
}
-/******************************************************************************
-* *
-* Paramètres : instr = instance à consulter. *
-* index = indice de l'opérande concerné. *
-* *
-* Description : Fournit un opérande donné d'une instruction. *
-* *
-* Retour : Opérande trouvée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
-{
- GArchOperand *result; /* Opérande à retourner */
- GArchOperand **ptr; /* Adresse dans le tableau */
-
- ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *));
-
- result = *ptr;
-
- g_object_ref(G_OBJECT(result));
-
- return result;
-}
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* old = ancienne opérande à détacher. *
-* new = nouvelle opérande à attacher. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dir = direction du lien recherché. *
+* type = type de lien à détecter. *
* *
-* Description : Remplace un opérande d'une instruction par un autre. *
+* Description : Détermine si un type de lien existe dans une instruction. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
+static bool _g_arch_instruction_has_link(const GArchInstruction *instr, compact_ins_link_t dir, InstructionLinkType type)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
-
- result = false;
-
- count = _g_arch_instruction_count_operands(instr);
-
- for (i = 0; i < count && !result; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
+ uint16_t i; /* Boucle de parcours */
- result = (op == old);
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- if (result)
- {
- rpl_item_in_flat_array(instr->operands, i - 1, &new, sizeof(GArchOperand *));
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- g_object_unref(G_OBJECT(old));
+ result = false;
- }
+ for (i = 0; i < instr->link_count && !result; i++)
+ result = COMPACT_INS_LINK_DIR(instr->links[i]) == dir;
return result;
@@ -828,45 +600,22 @@ bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* target = instruction à venir dissocier. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* type = type de lien à détecter. *
* *
-* Description : Détache un opérande liée d'une instruction. *
+* Description : Détermine si un type de lien amène à une instruction. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
+bool g_arch_instruction_has_src_link(const GArchInstruction *instr, InstructionLinkType type)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
-
- result = false;
-
- count = _g_arch_instruction_count_operands(instr);
- for (i = 0; i < count && !result; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
-
- result = (op == target);
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- if (result)
- {
- rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *));
-
- g_object_unref(G_OBJECT(target));
-
- }
+ result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_FROM, type);
return result;
@@ -875,78 +624,22 @@ bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
/******************************************************************************
* *
-* Paramètres : instr = instance à consulter. *
-* target = instruction à venir retrouver. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* type = type de lien à détecter. *
* *
-* Description : Détermine le chemin conduisant à un opérande. *
+* Description : Détermine si un type de lien émerge d'une instruction. *
* *
-* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target)
+bool g_arch_instruction_has_dest_link(const GArchInstruction *instr, InstructionLinkType type)
{
- char *result; /* Chemin à retourner */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
- int ret; /* Bilan d'une construction */
- char *sub_path; /* Sous-chemin emprunté */
-
- result = NULL;
-
- g_arch_instruction_lock_operands(instr);
-
- count = _g_arch_instruction_count_operands(instr);
-
- /* Première passe : accès direct */
-
- for (i = 0; i < count && result == NULL; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
-
- if (op == target)
- {
- ret = asprintf(&result, "%zu", i);
- if (ret == -1)
- {
- LOG_ERROR_N("asprintf");
- result = NULL;
- }
- }
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- /* Seconde passe : accès profond */
-
- for (i = 0; i < count && result == NULL; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
-
- sub_path = g_arch_operand_find_inner_operand_path(op, target);
-
- if (sub_path != NULL)
- {
- ret = asprintf(&result, "%zu:%s", i, sub_path);
- if (ret == -1)
- {
- LOG_ERROR_N("asprintf");
- result = NULL;
- }
-
- free(sub_path);
-
- }
-
- g_object_unref(G_OBJECT(op));
-
- }
+ bool result; /* Bilan à retourner */
- g_arch_instruction_unlock_operands(instr);
+ result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_TO, type);
return result;
@@ -955,104 +648,65 @@ char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchO
/******************************************************************************
* *
-* Paramètres : instr = instance à consulter. *
-* path = chemin d'accès à un opérande à retrouver. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dir = direction du lien recherché. *
+* linked = seconde instruction à considérer. *
* *
-* Description : Obtient l'opérande correspondant à un chemin donné. *
+* Description : Détermine si un lien existe entre deux instructions. *
* *
-* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path)
+static bool _g_arch_instruction_has_link_with(const GArchInstruction *instr, compact_ins_link_t dir, const GArchInstruction *linked)
{
- GArchOperand *result; /* Opérande trouvée à renvoyer */
- size_t index; /* Indice de l'opérande visé */
- char *end; /* Poursuite du parcours ? */
- GArchOperand *found; /* Opérande trouvé */
-
- result = NULL;
-
- g_arch_instruction_lock_operands(instr);
-
- /* Recherche au premier niveau */
-
- index = strtoul(path, &end, 10);
-
- if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
- {
- LOG_ERROR_N("strtoul");
- goto done;
- }
-
- found = _g_arch_instruction_get_operand(instr, index);
- if (found == NULL) goto done;
-
- if (*end == '\0')
- {
- result = found;
- goto done;
- }
-
- /* Recherche en profondeur */
-
- assert(*end == ':');
-
- result = g_arch_operand_get_inner_operand_from_path(found, end + 1);
+ bool result; /* Bilan à retourner */
+ uint16_t i; /* Boucle de parcours */
- g_object_unref(G_OBJECT(found));
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- done:
+ result = false;
- g_arch_instruction_unlock_operands(instr);
+ for (i = 0; i < instr->link_count && !result; i++)
+ result = COMPACT_INS_LINK_PTR(instr->links[i]) == linked;
return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction à mettre à jour. *
-* src = sélection de l'extrémité à traiter. *
-* lock = indique le sens du verrouillage à mener. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* src = seconde instruction à considérer. *
* *
-* Description : Met à disposition un encadrement des accès aux liens. *
+* Description : Détermine si une instruction est source d'une autre. *
* *
-* Retour : - *
+* Retour : Bilan du statut courant de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock)
+bool g_arch_instruction_has_src_link_with(const GArchInstruction *instr, const GArchInstruction *src)
{
- flat_array_t **array; /* Choix du tableau ciblé */
+ bool result; /* Bilan à retourner */
- array = (src ? &instr->from : &instr->to);
+ result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_FROM, src);
- if (lock)
- lock_flat_array(array);
- else
- unlock_flat_array(array);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* type = type de lien à détecter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dest = seconde instruction à considérer. *
* *
-* Description : Détermine si un type de lien existe dans une instruction. *
+* Description : Détermine si une instruction est destination d'une autre. *
* *
* Retour : Bilan du statut courant de l'instruction. *
* *
@@ -1060,30 +714,11 @@ void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, boo
* *
******************************************************************************/
-bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType type)
+bool g_arch_instruction_has_dest_link_with(const GArchInstruction *instr, const GArchInstruction *dest)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre de liens à parcourir */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dlink; /* Définition de destination */
-
- result = false;
-
- g_arch_instruction_lock_dest(instr);
- count = g_arch_instruction_count_destinations(instr);
-
- for (i = 0; i < count && !result; i++)
- {
- dlink = g_arch_instruction_get_destination(instr, i);
-
- result = (dlink->type == type);
-
- unref_instr_link(dlink);
-
- }
-
- g_arch_instruction_unlock_dest(instr);
+ result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_TO, dest);
return result;
@@ -1092,54 +727,53 @@ bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType ty
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les informations sont à manipuler. *
* dest = ligne visée par la liaison (côté destination). *
+* type = type de lien à construire. *
* *
-* Description : Détermine si un lien est déjà établi entre deux instructions.*
+* Description : Etablit un lien entre deux instructions. *
* *
-* Retour : Bilan de l'état actuel des liaisons. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruction *dest)
+void g_arch_instruction_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
- bool result; /* Bilan à retourner */
- size_t count; /* Nombre de liens à parcourir */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dlink; /* Définition de destination */
+ compact_ins_link_t new_from; /* Nouvel enregistrement #1 */
+ compact_ins_link_t new_to; /* Nouvel enregistrement #2 */
- result = false;
+ new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type);
+ ref_object(instr);
- g_arch_instruction_lock_dest(instr);
+ new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type);
+ ref_object(dest);
- count = g_arch_instruction_count_destinations(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ g_thick_object_lock(G_THICK_OBJECT(dest));
- for (i = 0; i < count && !result; i++)
- {
- dlink = g_arch_instruction_get_destination(instr, i);
-
- result = (dlink->linked == dest);
+ dest->links = realloc(dest->links, ++dest->link_count * sizeof(compact_ins_link_t));
- unref_instr_link(dlink);
+ dest->links[dest->link_count - 1] = new_from;
- }
+ instr->links = realloc(instr->links, ++instr->link_count * sizeof(compact_ins_link_t));
- g_arch_instruction_unlock_dest(instr);
+ instr->links[instr->link_count - 1] = new_to;
- return result;
+ g_thick_object_unlock(G_THICK_OBJECT(dest));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les informations sont à manipuler. *
* dest = ligne visée par la liaison (côté destination). *
* type = type de lien à construire. *
* *
-* Description : Etablit un lien entre deux instructions. *
+* Description : Supprime un lien entre deux instructions. *
* *
* Retour : - *
* *
@@ -1147,43 +781,59 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct
* *
******************************************************************************/
-void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
+void g_arch_instruction_unlink(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
- instr_link_t new_src; /* Nouveau lien à définir #1 */
- instr_link_t new_dst; /* Nouveau lien à définir #2 */
+ compact_ins_link_t old_from; /* Ancien enregistrement #1 */
+ compact_ins_link_t old_to; /* Ancien enregistrement #2 */
+ uint16_t i_from; /* Boucle de parcours #1 */
+ uint16_t i_to; /* Boucle de parcours #2 */
+ bool status; /* Bilan des recherches */
+
+ old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type);
+
+ old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type);
- /* Côté destination */
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ g_thick_object_lock(G_THICK_OBJECT(dest));
- new_src.linked = instr;
- new_src.type = type;
+ for (i_from = 0; i_from < dest->link_count; i_from++)
+ if (dest->links[i_from] == old_from)
+ break;
- ref_instr_link((&new_src));
+ for (i_to = 0; i_to < instr->link_count; i_to++)
+ if (instr->links[i_to] == old_to)
+ break;
- /* Côté point de départ */
+ assert((i_from < dest->link_count && i_to < instr->link_count)
+ || (i_from == dest->link_count && i_to == instr->link_count));
- new_dst.linked = dest;
- new_dst.type = type;
+ status = (i_from < dest->link_count && i_to < instr->link_count);
- ref_instr_link((&new_dst));
+ if (status)
+ {
+ if ((i_from + 1) < dest->link_count)
+ memmove(&dest->links[i_from], &dest->links[i_from + 1],
+ (dest->link_count - i_from - 1) * sizeof(compact_ins_link_t));
- /* Ajout dans le respect d'une cohérence globale */
+ dest->links = realloc(dest->links, --dest->link_count * sizeof(compact_ins_link_t));
- g_arch_instruction_lock_src(dest);
- g_arch_instruction_lock_dest(instr);
+ if ((i_to + 1) < instr->link_count)
+ memmove(&instr->links[i_to], &instr->links[i_to + 1],
+ (instr->link_count - i_to - 1) * sizeof(compact_ins_link_t));
- add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t));
+ instr->links = realloc(instr->links, --instr->link_count * sizeof(compact_ins_link_t));
- add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t));
+ }
- g_arch_instruction_unlock_dest(instr);
- g_arch_instruction_unlock_src(dest);
+ g_thick_object_unlock(G_THICK_OBJECT(dest));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les informations sont à manipuler. *
* dest = ligne visée par la liaison (côté destination). *
* old = ancien type de lien construit. *
* new = nouveau type de lien à construire. *
@@ -1199,67 +849,43 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
{
bool result; /* Bilan à retourner */
- size_t count; /* Raccourci pour la lecture */
- size_t i; /* Boucle de parcours */
- instr_link_t *slink; /* Définition de source */
- instr_link_t *dlink; /* Définition de destination */
-
- result = false;
+ compact_ins_link_t old_from; /* Ancien enregistrement #1 */
+ compact_ins_link_t new_from; /* Nouvel enregistrement #1 */
+ compact_ins_link_t old_to; /* Ancien enregistrement #2 */
+ compact_ins_link_t new_to; /* Nouvel enregistrement #2 */
+ uint16_t i_from; /* Boucle de parcours #1 */
+ uint16_t i_to; /* Boucle de parcours #2 */
- /**
- * Note : pour la récupération des liens de sources et de destinations,
- * on n'utilise pas les fonctions g_arch_instruction_get_(source|destination)(),
- * qui renvoient un pointeur non modifiable.
- *
- * On a en effet besoin de modifier le type de lien.
- */
+ old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, old);
+ new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, new);
+ old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, old);
+ new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, new);
- g_arch_instruction_lock_src(dest);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ g_thick_object_lock(G_THICK_OBJECT(dest));
- /* Côté destination */
-
- count = g_arch_instruction_count_sources(dest);
-
- for (i = 0; i < count; i++)
- {
- slink = get_flat_array_item(dest->from, i, sizeof(instr_link_t));
-
- if (slink->linked == instr && slink->type == old)
+ for (i_from = 0; i_from < dest->link_count; i_from++)
+ if (dest->links[i_from] == old_from)
break;
- }
-
- if (i == count)
- goto gaicl_exit;
+ for (i_to = 0; i_to < instr->link_count; i_to++)
+ if (instr->links[i_to] == old_to)
+ break;
- /* Côté point de départ */
+ assert((i_from < dest->link_count && i_to < instr->link_count)
+ || (i_from == dest->link_count && i_to == instr->link_count));
- count = g_arch_instruction_count_destinations(instr);
+ result = (i_from < dest->link_count && i_to < instr->link_count);
- for (i = 0; i < count; i++)
+ if (result)
{
- dlink = get_flat_array_item(instr->to, i, sizeof(instr_link_t));
-
- if (dlink->linked == dest && dlink->type == old)
- break;
-
+ dest->links[i_from] = new_from;
+ instr->links[i_to] = new_to;
}
- if (i == count)
- goto gaicl_exit;
-
- /* Si les deux extrémités sont raccord... */
-
- slink->type = new;
-
- dlink->type = new;
-
- result = true;
-
- gaicl_exit:
-
- g_arch_instruction_unlock_src(dest);
+ g_thick_object_unlock(G_THICK_OBJECT(dest));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
return result;
@@ -1280,116 +906,92 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
void g_arch_instruction_delete_all_links(GArchInstruction *instr)
{
- instr_link_t *link_src; /* Lien à supprimer #2 */
- GArchInstruction *other; /* Instruction de l'autre bout */
- size_t count; /* Quantié de liens présents */
- size_t i; /* Boucle de parcours */
- instr_link_t *link_dst; /* Lien à supprimer #1 */
+ GArchInstruction *linked; /* Autre instruction liée */
+ InstructionLinkType type; /* Type de liaison */
- /* Coté sources */
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- g_arch_instruction_lock_src(instr);
-
- while (count_flat_array_items(instr->from) > 0)
+ while (g_arch_instruction_count_src_links(instr) > 0)
{
- link_src = get_flat_array_item(instr->from, 0, sizeof(instr_link_t));
-
- other = link_src->linked;
+ linked = g_arch_instruction_get_linked_source(instr, 0, &type);
- g_arch_instruction_lock_dest(other);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- count = count_flat_array_items(other->to);
+ g_arch_instruction_unlink(linked, instr, type);
- for (i = 0; i < count; i++)
- {
- link_dst = get_flat_array_item(other->to, i, sizeof(instr_link_t));
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- if (link_dst->linked == instr && link_dst->type == link_src->type)
- {
- unref_instr_link(link_dst);
-
- rem_item_from_flat_array(&other->to, i, sizeof(instr_link_t));
-
- break;
-
- }
-
- }
-
- assert(i < count);
-
- g_arch_instruction_unlock_dest(other);
-
- unref_instr_link(link_src);
-
- rem_item_from_flat_array(&instr->from, 0, sizeof(instr_link_t));
+ unref_object(linked);
}
- g_arch_instruction_unlock_src(instr);
-
- /* Coté destinations */
-
- g_arch_instruction_lock_dest(instr);
-
- while (count_flat_array_items(instr->to) > 0)
+ while (g_arch_instruction_count_dest_links(instr) > 0)
{
- link_dst = get_flat_array_item(instr->to, 0, sizeof(instr_link_t));
+ linked = g_arch_instruction_get_linked_destination(instr, 0, &type);
- other = link_dst->linked;
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- g_arch_instruction_lock_src(other);
+ g_arch_instruction_unlink(instr, linked, type);
- count = count_flat_array_items(other->from);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- for (i = 0; i < count; i++)
- {
- link_src = get_flat_array_item(other->from, i, sizeof(instr_link_t));
+ unref_object(linked);
- if (link_src->linked == instr && link_src->type == link_dst->type)
- {
- unref_instr_link(link_src);
-
- rem_item_from_flat_array(&other->from, i, sizeof(instr_link_t));
+ }
- break;
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- }
+}
- }
- assert(i < count);
+/******************************************************************************
+* *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* dir = direction des liens à considérer. *
+* *
+* Description : Fournit la quantité d'instructions pointant vers une autre. *
+* *
+* Retour : Nombre de ces liens. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_arch_instruction_unlock_src(other);
+static size_t _g_arch_instruction_count_links(const GArchInstruction *instr, compact_ins_link_t dir)
+{
+ size_t result; /* Nombre de liens à renvoyer */
+ uint16_t i; /* Boucle de parcours */
- unref_instr_link(link_dst);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- rem_item_from_flat_array(&instr->to, 0, sizeof(instr_link_t));
+ result = 0;
- }
+ for (i = 0; i < instr->link_count; i++)
+ if (COMPACT_INS_LINK_DIR(instr->links[i]) == dir)
+ result++;
- g_arch_instruction_unlock_dest(instr);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
* *
-* Description : Fournit la quantité d'instructions pointant vers une autre. *
+* Description : Fournit la quantité d'instructions placées en source. *
* *
-* Retour : Nombre de ces origines. *
+* Retour : Nombre de ces liens. *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
+size_t g_arch_instruction_count_src_links(const GArchInstruction *instr)
{
size_t result; /* Nombre de liens à renvoyer */
- result = count_flat_array_items(instr->from);
+ result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_FROM);
return result;
@@ -1398,24 +1000,21 @@ size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* index = indice de l'élément à retrouver. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
* *
-* Description : Fournit les détails d'une origine d'une instruction donnée. *
+* Description : Fournit la quantité d'instructions placées en destination. *
* *
-* Retour : Lien déterminé vers une instruction d'origine. *
+* Retour : Nombre de ces liens. *
* *
* Remarques : - *
* *
******************************************************************************/
-const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index)
+size_t g_arch_instruction_count_dest_links(const GArchInstruction *instr)
{
- instr_link_t *result; /* Détails présents à renvoyer */
-
- result = get_flat_array_item(instr->from, index, sizeof(instr_link_t));
+ size_t result; /* Nombre de liens à renvoyer */
- ref_instr_link(result);
+ result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_TO);
return result;
@@ -1424,43 +1023,47 @@ const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* count = quantié de liens présents. [OUT] *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* index = indice de l'élément à retrouver. *
+* dir = direction des liens à considérer. *
+* type = type de lien enregistré. [OUT] *
* *
-* Description : Fournit tous les détails d'origine d'une instruction donnée. *
+* Description : Fournit les détails d'un lien donné avec une instruction. *
* *
-* Retour : Liens vers des instructions d'origine à libérer. *
+* Retour : Autre instruction pointée par l'instruction, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *count)
+static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *instr, size_t index, compact_ins_link_t dir, InstructionLinkType *type)
{
- instr_link_t *result; /* Détails présents à renvoyer */
- size_t i; /* Boucle de parcours */
- const instr_link_t *link; /* Lien à fournir */
-
- g_arch_instruction_lock_src(instr);
+ GArchInstruction *result; /* Instance ciblée à renvoyer */
+ uint16_t i; /* Boucle de parcours */
- *count = g_arch_instruction_count_sources(instr);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- if (*count == 0)
- result = NULL;
+ result = NULL;
+ *type = ILT_COUNT;
- else
+ for (i = 0; i < instr->link_count; i++)
{
- result = (instr_link_t *)malloc(*count * sizeof(instr_link_t));
+ if (COMPACT_INS_LINK_DIR(instr->links[i]) != dir)
+ continue;
- for (i = 0; i < *count; i++)
+ if (index == 0)
{
- link = g_arch_instruction_get_source(instr, i);
- memcpy(&result[i], link, sizeof(instr_link_t));
+ result = COMPACT_INS_LINK_PTR(instr->links[i]);
+ *type = COMPACT_INS_LINK_TYPE(instr->links[i]);
}
+ else
+ index--;
+
}
- g_arch_instruction_unlock_src(instr);
+ if (result != NULL)
+ ref_object(result);
return result;
@@ -1469,21 +1072,23 @@ instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *co
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
+* index = indice de l'élément à retrouver. *
+* type = type de lien enregistré. [OUT] *
* *
-* Description : Donne le nombre d'instructions non naturellement suivantes. *
+* Description : Fournit les détails d'une source donnée d'une instruction. *
* *
-* Retour : Nombre de ces destinations. *
+* Retour : Autre instruction pointée par l'instruction, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
+GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *instr, size_t index, InstructionLinkType *type)
{
- size_t result; /* Nombre de liens à renvoyer */
+ GArchInstruction *result; /* Instance ciblée à renvoyer */
- result = count_flat_array_items(instr->to);
+ result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_FROM, type);
return result;
@@ -1492,71 +1097,54 @@ size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
+* Paramètres : instr = instruction dont les liens sont à consulter. *
* index = indice de l'élément à retrouver. *
+* type = type de lien enregistré. [OUT] *
* *
-* Description : Fournit les détails d'une destination d'une instruction. *
+* Description : Fournit les détails d'une destination donnée d'une instruct. *
* *
-* Retour : Lien déterminé vers une instruction de destination. *
+* Retour : Autre instruction pointée par l'instruction, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index)
+GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *instr, size_t index, InstructionLinkType *type)
{
- instr_link_t *result; /* Détails présents à renvoyer */
-
- result = get_flat_array_item(instr->to, index, sizeof(instr_link_t));
+ GArchInstruction *result; /* Instance ciblée à renvoyer */
- ref_instr_link(result);
+ result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_TO, type);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATION DES OPERANDES */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* type = type de lien recherché. *
+* Paramètres : instr = instance à consulter. *
* *
-* Description : Fournit la destination d'une instruction et d'un type donné. *
+* Description : Indique la quantité d'opérandes présents dans l'instruction. *
* *
-* Retour : Instruction de destination trouvée ou NULL. *
+* Retour : Nombre d'opérandes attachés. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type)
+size_t g_arch_instruction_count_operands(const GArchInstruction *instr)
{
- GArchInstruction *result; /* Résultat à remonter */
- size_t count; /* Nombre de liens à parcourir */
- size_t i; /* Boucle de parcours */
- const instr_link_t *dest; /* Destination à étudier */
-
- result = NULL;
-
- g_arch_instruction_lock_dest(instr);
-
- count = g_arch_instruction_count_destinations(instr);
-
- for (i = 0; i < count && result == NULL; i++)
- {
- dest = g_arch_instruction_get_destination(instr, i);
-
- if (dest->type == type)
- {
- result = dest->linked;
- g_object_ref(G_OBJECT(result));
- }
+ size_t result; /* Décompte à retourner */
- unref_instr_link(dest);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- }
-
- g_arch_instruction_unlock_dest(instr);
+ result = count_flat_array_items(instr->operands);
return result;
@@ -1565,56 +1153,45 @@ GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *ins
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* count = quantié de liens présents. [OUT] *
+* Paramètres : instr = instance à mettre à jour. *
+* operand = instruction à venir associer. *
* *
-* Description : Fournit tous les détails de destination d'une instruction. *
+* Description : Attache un opérande supplémentaire à une instruction. *
* *
-* Retour : Liens vers des instructions de destination à libérer. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_t *count)
+void g_arch_instruction_attach_operand(GArchInstruction *instr, GArchOperand *operand)
{
- instr_link_t *result; /* Détails présents à renvoyer */
- size_t i; /* Boucle de parcours */
- const instr_link_t *link; /* Lien à fournir */
-
- g_arch_instruction_lock_dest(instr);
-
- *count = g_arch_instruction_count_destinations(instr);
+ GSingletonFactory *factory; /* Unise à instances uniques */
+ GSingletonCandidate *singleton; /* Instance retenue */
+ GArchOperand *stored; /* Forme d'opérande conservée */
- if (*count == 0)
- result = NULL;
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- else
- {
- result = (instr_link_t *)malloc(*count * sizeof(instr_link_t));
+ factory = get_operands_factory();
- for (i = 0; i < *count; i++)
- {
- link = g_arch_instruction_get_destination(instr, i);
- memcpy(&result[i], link, sizeof(instr_link_t));
- }
+ singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand));
- }
+ unref_object(factory);
- g_arch_instruction_unlock_dest(instr);
+ stored = G_ARCH_OPERAND(singleton);
- return result;
+ add_item_to_flat_array(&instr->operands, &stored, sizeof(GArchOperand *));
}
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : instr = instance à mettre à jour. *
+* old = ancienne opérande à détacher. *
+* new = nouvelle opérande à attacher. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Remplace un opérande d'une instruction par un autre. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -1622,40 +1199,47 @@ instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_
* *
******************************************************************************/
-static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
{
bool result; /* Bilan à retourner */
- uleb128_t count; /* Nombre de liens à charger */
- uleb128_t i; /* Boucle de parcours */
- GArchInstruction *linked; /* Lien vers une instruction */
- uleb128_t type; /* Valeur ULEB128 à charger */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ GSingletonFactory *factory; /* Unise à instances uniques */
+ GSingletonCandidate *singleton; /* Instance retenue */
+ GArchOperand *stored; /* Forme d'opérande conservée */
- g_arch_instruction_lock_dest(instr);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- result = unpack_uleb128(&count, pbuf);
+ result = false;
- for (i = 0; i < count && result; i++)
+ count = g_arch_instruction_count_operands(instr);
+
+ for (i = 0; i < count && !result; i++)
{
- linked = G_ARCH_INSTRUCTION(g_object_storage_unpack_object(storage, "instructions", pbuf));
- if (linked == NULL)
- {
- result = false;
- break;
- }
+ op = g_arch_instruction_get_operand(instr, i);
- result = unpack_uleb128(&type, pbuf);
- if (!result)
- {
- g_object_unref(G_OBJECT(linked));
- break;
- }
+ result = (op == old);
- g_arch_instruction_link_with(instr, linked, type);
- g_object_unref(G_OBJECT(linked));
+ unref_object(op);
}
- g_arch_instruction_unlock_dest(instr);
+ if (result)
+ {
+ factory = get_operands_factory();
+
+ singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(new));
+
+ unref_object(factory);
+
+ stored = G_ARCH_OPERAND(singleton);
+
+ rpl_item_in_flat_array(instr->operands, i - 1, &stored, sizeof(GArchOperand *));
+
+ unref_object(old);
+
+ }
return result;
@@ -1664,11 +1248,10 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter.*
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instance à mettre à jour. *
+* target = instruction à venir dissocier. *
* *
-* Description : Sauvegarde toutes les destinations d'une instruction. *
+* Description : Détache un opérande liée d'une instruction. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -1676,87 +1259,67 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec
* *
******************************************************************************/
-bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+bool g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
{
bool result; /* Bilan à retourner */
- size_t count; /* Nombre d'éléments à traiter */
- size_t kept; /* Nombre de liens conservés */
+ size_t count; /* Nombre d'opérandes en place */
size_t i; /* Boucle de parcours */
- const instr_link_t *link; /* Lien vers une instruction */
-
- g_arch_instruction_lock_dest(instr);
+ GArchOperand *op; /* Opérande à manipuler */
- count = g_arch_instruction_count_destinations(instr);
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- /**
- * Le type de lien ILT_REF n'est mis en place que lors de la création
- * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place
- * dynamiquement lors de la restauration de ces derniers.
- */
+ result = false;
- kept = 0;
+ count = g_arch_instruction_count_operands(instr);
- for (i = 0; i < count; i++)
+ for (i = 0; i < count && !result; i++)
{
- link = g_arch_instruction_get_destination(instr, i);
+ op = g_arch_instruction_get_operand(instr, i);
- if (link->type != ILT_REF)
- kept++;
+ result = (op == target);
- unref_instr_link(link);
+ unref_object(op);
}
- result = pack_uleb128((uleb128_t []){ kept }, pbuf);
-
- for (i = 0; i < count && result; i++)
+ if (result)
{
- link = g_arch_instruction_get_destination(instr, i);
-
- if (link->type != ILT_REF)
- {
- result = g_object_storage_pack_object(storage, "instructions",
- G_SERIALIZABLE_OBJECT(link->linked), pbuf);
-
- if (result)
- result = pack_uleb128((uleb128_t []){ link->type }, pbuf);
-
- }
+ rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *));
- unref_instr_link(link);
+ unref_object(target);
}
- g_arch_instruction_unlock_dest(instr);
-
return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* CONVERSIONS DU FORMAT DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
+* Paramètres : instr = instance à consulter. *
+* index = indice de l'opérande concerné. *
* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
+* Description : Fournit un opérande donné d'une instruction. *
* *
-* Retour : Mot clef de bas niveau. *
+* Retour : Opérande trouvée. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_arch_instruction_get_keyword(GArchInstruction *instr)
+GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
{
- const char *result; /* Désignation à retourner */
+ GArchOperand *result; /* Opérande à retourner */
+ GArchOperand **ptr; /* Adresse dans le tableau */
+
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(instr)));
- result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_keyword(instr);
+ ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *));
+
+ result = *ptr;
+
+ ref_object(result);
return result;
@@ -1765,450 +1328,396 @@ const char *g_arch_instruction_get_keyword(GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
+* Paramètres : instr = instance à consulter. *
+* target = instruction à venir retrouver. *
* *
-* Description : Construit un petit résumé concis de l'instruction. *
+* Description : Détermine le chemin conduisant à un opérande. *
* *
-* Retour : Chaîne de caractères à libérer après usage ou NULL. *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_arch_instruction_build_tooltip(const GArchInstruction *instr)
+char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target)
{
- char *result; /* Description à retourner */
- GArchInstructionClass *class; /* Classe des instructions */
+ char *result; /* Chemin à retourner */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ int ret; /* Bilan d'une construction */
+ char *sub_path; /* Sous-chemin emprunté */
- class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+ result = NULL;
- if (class->build_tooltip != NULL)
- result = class->build_tooltip(instr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
- else
- result = NULL;
+ count = g_arch_instruction_count_operands(instr);
- return result;
+ /* Première passe : accès direct */
-}
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+ if (op == target)
+ {
+ ret = asprintf(&result, "%zu", i);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+ }
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* *
-* Description : Fournit une description pour l'instruction manipulée. *
-* *
-* Retour : Chaîne de caractères avec balises éventuelles. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(op);
-const char *g_arch_instruction_get_description(const GArchInstruction *instr)
-{
- const char *result; /* Description à retourner */
+ }
- result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_desc(instr);
+ /* Seconde passe : accès profond */
- return result;
-
-}
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+ sub_path = NULL;//g_arch_operand_find_inner_operand_path(op, target);
+ if (sub_path != NULL)
+ {
+ ret = asprintf(&result, "%zu:%s", i, sub_path);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
-/* ---------------------------------------------------------------------------------- */
-/* OFFRE DE CAPACITES DE GENERATION */
-/* ---------------------------------------------------------------------------------- */
+ free(sub_path);
+ }
-/******************************************************************************
-* *
-* Paramètres : instr = générateur à consulter. *
-* *
-* Description : Indique le nombre de ligne prêtes à être générées. *
-* *
-* Retour : Nombre de lignes devant apparaître au final. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(op);
-static size_t g_arch_instruction_count_lines(const GArchInstruction *instr)
-{
- return 1;
+ }
-}
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+ return result;
-#ifdef INCLUDE_GTK_SUPPORT
+}
/******************************************************************************
* *
-* Paramètres : instr = générateur à consulter. *
-* x = position géographique sur la ligne concernée. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* cursor = emplacement à constituer. [OUT] *
+* Paramètres : instr = instance à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
* *
-* Description : Retrouve l'emplacement correspondant à une position donnée. *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
* *
-* Retour : - *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_arch_instruction_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor)
+GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path)
{
- *cursor = g_binary_cursor_new();
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ size_t index; /* Indice de l'opérande visé */
+ char *end; /* Poursuite du parcours ? */
+ GArchOperand *found; /* Opérande trouvé */
- g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range));
+ result = NULL;
-}
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+ /* Recherche au premier niveau */
-/******************************************************************************
-* *
-* Paramètres : instr = générateur à consulter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* cursor = emplacement à analyser. *
-* *
-* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
-* *
-* Retour : Bilan de la détermination, utilisable en comparaisons. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ index = strtoul(path, &end, 10);
-static int g_arch_instruction_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor)
-{
- int result; /* Conclusion à retourner */
- vmpa2t addr; /* Autre emplacement à comparer*/
+ if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
+ {
+ LOG_ERROR_N("strtoul");
+ goto done;
+ }
+
+ found = g_arch_instruction_get_operand(instr, index);
+ if (found == NULL) goto done;
+
+ if (*end == '\0')
+ {
+ result = found;
+ goto done;
+ }
+
+ /* Recherche en profondeur */
+
+ assert(*end == ':');
+
+ result = NULL;//g_arch_operand_get_inner_operand_from_path(found, end + 1);
- assert(G_IS_BINARY_CURSOR(cursor));
+ unref_object(found);
- g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr);
+ done:
- result = cmp_mrange_with_vmpa(&instr->range, &addr);
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
return result;
}
-#endif
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE CONSERVATION ET RESTAURATION */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : instr = générateur à consulter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Renseigne sur les propriétés liées à un générateur. *
+* Description : Charge un objet depuis un flux de données. *
* *
-* Retour : Propriétés particulières associées. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat)
+static bool g_arch_instruction_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
- return BLF_HAS_CODE;
+ bool result; /* Bilan à retourner */
+ uleb128_t extra; /* Données embarquées */
+
+ /* Propriétés internes */
+
+ result = load_uleb128(&extra, fd);
+
+ if (result)
+ g_thick_object_set_extra(G_THICK_OBJECT(object), extra);
+
+ /* Liaisons avec d'autres instructions */
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à représenter. *
-* line = ligne de rendu à compléter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* content = éventuel contenu binaire brut à imprimer. *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
+* Description : Sauvegarde un objet dans un flux de données. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
+static bool g_arch_instruction_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
- const char *key; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
- size_t count; /* Nombre d'opérandes en place */
+ bool result; /* Bilan à retourner */
+ GArchInstruction *instr; /* Version spécialisée */
+ size_t src_count; /* Quantité de sources */
+ size_t dest_count; /* Quantité de destinations */
+ off64_t *ins_offsets; /* Emplacements d'instructions */
size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
+ GArchInstruction *linked; /* Instruction liée */
+ size_t op_count; /* Quantité d'opérandes */
+ off64_t *op_offsets; /* Emplacements d'opérandes */
+ GArchOperand *op; /* Opérande à traiter */
+ guint extra; /* Données embarquées */
+ InstructionLinkType type; /* Type de lien */
- g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range));
+ assert(g_thick_object_check_lock(G_THICK_OBJECT(object)));
- g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range));
+ /* Préparation des références aux instructions liées */
- g_buffer_line_fill_content(line, DLC_BINARY, content, &instr->range, VMPA_NO_PHYSICAL);
+ instr = G_ARCH_INSTRUCTION(object);
- /* Instruction proprement dite */
+ src_count = g_arch_instruction_count_src_links(instr);
+ dest_count = g_arch_instruction_count_dest_links(instr);
- key = g_arch_instruction_get_keyword(instr);
- klen = strlen(key);
+ ins_offsets = malloc((src_count + dest_count) * sizeof(off64_t));
- g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, G_OBJECT(instr));
+ for (i = 0; i < src_count && result; i++)
+ {
+ linked = g_arch_instruction_get_linked_source(instr, i, (InstructionLinkType []) { 0 });
- /* Liste des opérandes */
+ result = g_object_storage_store_object(storage, "instructions",
+ G_SERIALIZABLE_OBJECT(linked), &ins_offsets[i]);
- g_arch_instruction_lock_operands(instr);
+ unref_object(linked);
- count = _g_arch_instruction_count_operands(instr);
+ }
- if (count > 0)
+ for (i = 0; i < dest_count && result; i++)
{
- op = _g_arch_instruction_get_operand(instr, 0);
- g_arch_operand_print(op, line);
- g_object_unref(G_OBJECT(op));
+ linked = g_arch_instruction_get_linked_destination(instr, i, (InstructionLinkType []) { 0 });
- for (i = 1; i < count; i++)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
+ result = g_object_storage_store_object(storage, "instructions",
+ G_SERIALIZABLE_OBJECT(linked), &ins_offsets[src_count + i]);
- op = _g_arch_instruction_get_operand(instr, i);
+ unref_object(linked);
- g_arch_operand_print(op, line);
+ }
- g_object_unref(G_OBJECT(op));
+ if (!result)
+ goto exit_with_ins_off;
- }
+ /* Préparation des références aux opérandes embarqués */
- }
+ op_count = g_arch_instruction_count_operands(instr);
- g_arch_instruction_unlock_operands(instr);
+ op_offsets = malloc(op_count * sizeof(off64_t));
-}
+ for (i = 0; i < op_count && result; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+ result = g_object_storage_store_object(storage, "operandss",
+ G_SERIALIZABLE_OBJECT(op), &op_offsets[i]);
-/******************************************************************************
-* *
-* Paramètres : instr = générateur à utiliser pour l'impression. *
-* line = ligne de rendu à compléter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* content = éventuel contenu binaire brut à imprimer. *
-* *
-* Description : Imprime dans une ligne de rendu le contenu représenté. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(op);
-static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
-{
- G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat, content);
+ }
-}
+ if (!result)
+ goto exit_with_op_off;
+ /* Propriétés internes */
+ extra = g_thick_object_get_extra(G_THICK_OBJECT(object));
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION ET RECHARGEMENT DES DONNEES */
-/* ---------------------------------------------------------------------------------- */
+ result = store_uleb128((uleb128_t []) { extra }, fd);
+ if (!result) goto exit;
+ /* Liaisons avec d'autres instructions */
-/******************************************************************************
-* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ instr = G_ARCH_INSTRUCTION(object);
-static bool _g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à consulter*/
- uleb128_t value; /* Valeur ULEB128 à charger */
- uleb128_t count; /* Nombre d'éléments à traiter */
- uleb128_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à traiter */
+ src_count = g_arch_instruction_count_src_links(instr);
+ dest_count = g_arch_instruction_count_dest_links(instr);
- extra = GET_ARCH_INSTR_EXTRA(instr);
+ result = store_uleb128((uleb128_t []) { src_count }, fd);
+ if (!result) goto exit;
- LOCK_GOBJECT_EXTRA(extra);
+ result = store_uleb128((uleb128_t []) { dest_count }, fd);
+ if (!result) goto exit;
- result = unpack_uleb128(&value, pbuf);
+ for (i = 0; i < src_count && result; i++)
+ {
+ linked = g_arch_instruction_get_linked_source(instr, i, &type);
- if (result)
- extra->uid = value;
+ result = store_uleb128((uleb128_t []) { type }, fd);
- if (result)
- {
- result = unpack_uleb128(&value, pbuf);
+ unref_object(linked);
if (result)
- extra->flags = value;
+ result = store_uleb128((uleb128_t []) { ins_offsets[i] }, fd);
}
- UNLOCK_GOBJECT_EXTRA(extra);
-
- if (result)
- result = unpack_mrange(&instr->range, pbuf);
-
- if (result)
+ for (i = 0; i < dest_count && result; i++)
{
- result = unpack_uleb128(&count, pbuf);
+ linked = g_arch_instruction_get_linked_destination(instr, i, &type);
- for (i = 0; i < count && result; i++)
- {
- op = G_ARCH_OPERAND(g_object_storage_unpack_object(storage, "operands", pbuf));
- result = (op != NULL);
+ result = store_uleb128((uleb128_t []) { type }, fd);
- if (result)
- g_arch_instruction_attach_extra_operand(instr, op);
+ unref_object(linked);
- }
+ if (result)
+ result = store_uleb128((uleb128_t []) { ins_offsets[src_count + i] }, fd);
}
- if (result)
- result = g_arch_instruction_load_destinations(instr, storage, pbuf);
-
- return result;
+ /* Opérandes embarqués */
-}
+ result = store_uleb128((uleb128_t []) { op_count }, fd);
+ if (!result) goto exit;
+ for (i = 0; i < op_count && result; i++)
+ result = store_uleb128((uleb128_t []) { op_offsets[i] }, fd);
-/******************************************************************************
-* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ exit:
+ exit_with_op_off:
-static bool g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *class; /* Classe à activer */
+ free(op_offsets);
- class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+ exit_with_ins_off:
- result = class->load(instr, storage, pbuf);
+ free(ins_offsets);
return result;
}
-/******************************************************************************
-* *
-* Paramètres : instr = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-static bool _g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- instr_extra_data_t *extra; /* Données insérées à consulter*/
- size_t count; /* Nombre d'éléments à traiter */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à traiter */
-
- extra = GET_ARCH_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
- result = pack_uleb128((uleb128_t []){ extra->uid }, pbuf);
- if (result)
- result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf);
- UNLOCK_GOBJECT_EXTRA(extra);
- if (result)
- result = pack_mrange(&instr->range, pbuf);
- if (result)
- {
- g_arch_instruction_lock_operands(instr);
- count = _g_arch_instruction_count_operands(instr);
- result = pack_uleb128((uleb128_t []){ count }, pbuf);
- for (i = 0; i < count && result; i++)
- {
- op = _g_arch_instruction_get_operand(instr, i);
- result = g_object_storage_pack_object(storage, "operands", G_SERIALIZABLE_OBJECT(op), pbuf);
- g_object_unref(G_OBJECT(op));
- }
- g_arch_instruction_unlock_operands(instr);
- }
- if (result)
- result = g_arch_instruction_store_destinations(instr, storage, pbuf);
+#if 0
- return result;
-}
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction quelconque à traiter. *
+* type = type de procédure à utiliser. *
+* proc = représentation de l'architecture utilisée. *
+* context = contexte associé à la phase de désassemblage. *
+* format = accès aux données du binaire d'origine. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Complète un désassemblage accompli pour une instruction. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *class; /* Classe à activer */
+ GArchInstructionClass *class; /* Classe des instructions */
class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
- result = class->store(instr, storage, pbuf);
-
- return result;
+ if (class->call_hook != NULL)
+ class->call_hook(instr, type, proc, context, format);
}
+
+
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 3c9c149..98bc73e 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction.h - prototypes pour la gestion générique des instructions
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,194 +25,118 @@
#define _ARCH_INSTRUCTION_H
-#include <sys/types.h>
+#include <stdbool.h>
+#include <stdint.h>
-#include "context.h"
#include "operand.h"
-#include "register.h"
#include "vmpa.h"
-#include "../analysis/type.h"
-#include "../common/packed.h"
-#include "../format/executable.h"
+#include "../glibext/helpers.h"
+#include "../glibext/portion.h"
-#define G_TYPE_ARCH_INSTRUCTION g_arch_instruction_get_type()
-#define G_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction))
-#define G_IS_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type()))
-#define G_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass))
-#define G_IS_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_INSTRUCTION))
-#define G_ARCH_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass))
+/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */
-/* Définition générique d'une instruction d'architecture (instance) */
-typedef struct _GArchInstruction GArchInstruction;
+#define G_TYPE_ARCH_INSTRUCTION (g_arch_instruction_get_type())
-/* Définition générique d'une instruction d'architecture (classe) */
-typedef struct _GArchInstructionClass GArchInstructionClass;
+DECLARE_GTYPE(GArchInstruction, g_arch_instruction, G, ARCH_INSTRUCTION);
-/* Drapeaux pour informations complémentaires */
-
-#define AIF_USER_BIT 4
-
-typedef enum _ArchInstrFlag
-{
- AIF_NONE = (0 << 0), /* Aucune information */
- AIF_ROUTINE_START = (1 << 0), /* Début de routine */
- AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */
- AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */
- AIF_CALL = (1 << 3), /* Instruction d'appel */
-
- AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */
- AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */
-
-} ArchInstrFlag;
-
/* Type pour les types d'instructions */
typedef uint16_t itid_t;
-/* Types de crochet de traitement */
-typedef enum _InstrProcessHook
-{
- IPH_FETCH, /* Itinéraire de désassemblage */
- IPH_LINK, /* Edition des liens */
- IPH_POST, /* Résolution des symboles */
-
- IPH_COUNT
-
-} InstrProcessHook;
-
-
-/* Indique le type défini pour une instruction d'architecture. */
-GType g_arch_instruction_get_type(void);
+/* Fournit l'identifiant correspondant à un type d'instructions. */
+itid_t g_arch_instruction_get_type_id(const GArchInstruction *);
/* Indique l'encodage d'une instruction de façon détaillée. */
-const char *g_arch_instruction_get_encoding(const GArchInstruction *);
-
-/* Ajoute une information complémentaire à une instruction. */
-bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag);
+char *g_arch_instruction_get_encoding(const GArchInstruction *);
-/* Retire une information complémentaire à une instruction. */
-bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstrFlag);
-
-/* Détermine si une instruction possède un fanion particulier. */
-bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstrFlag);
+/* Fournit le nom humain de l'instruction manipulée. */
+char *g_arch_instruction_get_keyword(const GArchInstruction *);
-/* Fournit les informations complémentaires d'une instruction. */
-ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *);
-/* Définit l'identifiant unique pour un ensemble d'instructions. */
-void g_arch_instruction_set_unique_id(GArchInstruction *, itid_t);
+ /* Type de masques pour les encodages d'instructions */
+typedef enum _InstructionBytesMask
+{
+ /**
+ * Correspond aux bits fixes : pas de valeurs de registre ni de valeur entière.
+ */
+ IBM_LOOSE,
-/* Fournit l'identifiant unique pour un ensemble d'instructions. */
-itid_t g_arch_instruction_get_unique_id(const GArchInstruction *);
+ /**
+ * Dissimulation des références à des éléments externes pouvant varier avec
+ * entre compilations : adresses de saut ou d'appel, références vers des tables,
+ * etc.
+ */
+ IBM_LOCAL,
+ /**
+ * Dissimulation des déplacements à partir d'une base.
+ */
+ IBM_STRICT,
-/**
- * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut
- * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références
- * circulaires.
- *
- * On procède donc à une seconde déclaration, en attendant éventuellement mieux.
- */
+ /**
+ * Conservation de toutes les valeurs immédiates et dissimulation des registres.
+ */
+ IBM_LARGE,
-/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
-typedef struct _GArchProcessor GArchProcessor;
+ IBM_COUNT
+} InstructionBytesMask;
-/* Complète un désassemblage accompli pour une instruction. */
-typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *);
-
-/* Complète un désassemblage accompli pour une instruction. */
-void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
-/* Définit la localisation d'une instruction. */
-void g_arch_instruction_set_range(GArchInstruction *, const mrange_t *);
+/* Calcule la localisation d'une instruction. */
+void g_arch_instruction_compute_range(GArchInstruction *, GBinaryPortion *, const vmpa2t *, phys_t);
/* Fournit la place mémoire d'une instruction. */
-const mrange_t *g_arch_instruction_get_range(const GArchInstruction *);
-
-
-
-/* Fournit la localisation d'une instruction. */
-void g_arch_instruction_get_location(const GArchInstruction *, off_t *, off_t *, vmpa_t *) __attribute__ ((deprecated));
+bool g_arch_instruction_get_range(const GArchInstruction *, mrange_t *);
+#define AIF_USER_BIT 4
-/* Liste les registres lus et écrits par l'instruction. */
-void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *) __attribute__ ((deprecated));
+typedef enum _ArchInstructionFlag
+{
+ AIF_NONE = (0 << 0), /* Aucune information */
+ AIF_ROUTINE_START = (1 << 0), /* Début de routine */
+ AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */
+ AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */
+ AIF_CALL = (1 << 3), /* Instruction d'appel */
+ AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */
+ AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */
+} ArchInstructionFlag;
-/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
+#define AIF_USER_FLAG(n) (1 << (AIF_USER_BIT + n))
-/* Verrouille les accès à la liste des opérandes. */
-void g_arch_instruction_lock_operands(GArchInstruction *);
+/* Ajoute une information complémentaire à une instruction. */
+bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstructionFlag);
-/* Déverrouille les accès à la liste des opérandes. */
-void g_arch_instruction_unlock_operands(GArchInstruction *);
+/* Retire une information complémentaire à une instruction. */
+bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstructionFlag);
-/* Attache un opérande supplémentaire à une instruction. */
-void g_arch_instruction_attach_extra_operand(GArchInstruction *, GArchOperand *);
+/* Détermine si une instruction possède un fanion particulier. */
+bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstructionFlag);
-/* Indique la quantité d'opérandes présents dans l'instruction. */
-size_t _g_arch_instruction_count_operands(const GArchInstruction *);
+/* Fournit les particularités de l'instruction. */
+ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *);
-/* Fournit un opérande donné d'une instruction. */
-GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t);
-/* Remplace un opérande d'une instruction par un autre. */
-bool _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
+/* Types de crochet de traitement */
+typedef enum _InstrProcessHook
+{
+ IPH_FETCH, /* Itinéraire de désassemblage */
+ IPH_LINK, /* Edition des liens */
+ IPH_POST, /* Résolution des symboles */
-/* Détache un opérande liée d'une instruction. */
-bool _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
-
-
-#define g_arch_instruction_count_operands(ins) \
- ({ \
- size_t __result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_count_operands(ins); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
-
-#define g_arch_instruction_get_operand(ins, idx) \
- ({ \
- GArchOperand *__result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_get_operand(ins, idx); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
-
-#define g_arch_instruction_replace_operand(ins, o, n) \
- ({ \
- bool __result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_replace_operand(ins, o, n); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
-
-#define g_arch_instruction_detach_operand(ins, o) \
- ({ \
- bool __result; \
- g_arch_instruction_lock_operands(ins); \
- __result = _g_arch_instruction_detach_operand(ins, o); \
- g_arch_instruction_unlock_operands(ins); \
- __result; \
- })
+ IPH_COUNT
+} InstrProcessHook;
-/* Détermine le chemin conduisant à un opérande. */
-char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *);
-/* Obtient l'opérande correspondant à un chemin donné. */
-GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *);
@@ -236,30 +160,24 @@ typedef enum _InstructionLinkType
} InstructionLinkType;
-/* Déscription d'une liaison entre deux instructions */
-typedef struct _instr_link_t
-{
- GArchInstruction *linked; /* Autre instruction liée */
- InstructionLinkType type; /* Type de liaison */
-
-} instr_link_t;
-
-#define ref_instr_link(l) g_object_ref(G_OBJECT(l->linked));
-#define unref_instr_link(l) g_object_unref(G_OBJECT(l->linked));
+/* Détermine si un type de lien amène à une instruction. */
+bool g_arch_instruction_has_src_link(const GArchInstruction *, InstructionLinkType);
+/* Détermine si un type de lien émerge d'une instruction. */
+bool g_arch_instruction_has_dest_link(const GArchInstruction *, InstructionLinkType);
-/* Met à disposition un encadrement des accès aux liens. */
-void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool);
+/* Détermine si une instruction est source d'une autre. */
+bool g_arch_instruction_has_src_link_with(const GArchInstruction *, const GArchInstruction *);
-/* Détermine si un type de lien existe dans une instruction. */
-bool g_arch_instruction_has_link(GArchInstruction *, InstructionLinkType);
-
-/* Détermine si un lien est déjà établi entre deux instructions. */
-bool g_arch_instruction_has_link_to(GArchInstruction *, const GArchInstruction *);
+/* Détermine si une instruction est destination d'une autre. */
+bool g_arch_instruction_has_dest_link_with(const GArchInstruction *, const GArchInstruction *);
/* Etablit un lien entre deux instructions. */
-void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType);
+void g_arch_instruction_link(GArchInstruction *, GArchInstruction *, InstructionLinkType);
+
+/* Supprime un lien entre deux instructions. */
+void g_arch_instruction_unlink(GArchInstruction *, GArchInstruction *, InstructionLinkType);
/* Change la nature d'un lien entre deux instructions. */
bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
@@ -267,46 +185,72 @@ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, Inst
/* Supprime tous les liens établis avec d'autres instructions. */
void g_arch_instruction_delete_all_links(GArchInstruction *);
-#define g_arch_instruction_lock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true)
-#define g_arch_instruction_unlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false)
+/* Fournit la quantité d'instructions placées en source. */
+size_t g_arch_instruction_count_src_links(const GArchInstruction *);
-/* Fournit la quantité d'instructions pointant vers une autre. */
-size_t g_arch_instruction_count_sources(const GArchInstruction *);
+/* Fournit la quantité d'instructions placées en destination. */
+size_t g_arch_instruction_count_dest_links(const GArchInstruction *);
-/* Fournit les détails d'une origine d'une instruction donnée. */
-const instr_link_t *g_arch_instruction_get_source(GArchInstruction *, size_t);
+/* Fournit les détails d'une source donnée d'une instruction. */
+GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *, size_t, InstructionLinkType *);
-/* Fournit tous les détails d'origine d'une instruction donnée. */
-instr_link_t *g_arch_instruction_get_sources(GArchInstruction *, size_t *);
+/* Fournit les détails d'une destination donnée d'une instruction. */
+GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *, size_t, InstructionLinkType *);
-#define g_arch_instruction_lock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true)
-#define g_arch_instruction_unlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false)
-/* Donne le nombre d'instructions non naturellement suivantes. */
-size_t g_arch_instruction_count_destinations(const GArchInstruction *);
-/* Fournit les détails d'une destination d'une instruction. */
-const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *, size_t);
+/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
-/* Fournit la destination d'une instruction et d'un type donné. */
-GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *, InstructionLinkType);
-/* Fournit tous les détails de destination d'une instruction. */
-instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *, size_t *);
+/* Indique la quantité d'opérandes présents dans l'instruction. */
+size_t g_arch_instruction_count_operands(const GArchInstruction *);
+/* Attache un opérande supplémentaire à une instruction. */
+void g_arch_instruction_attach_operand(GArchInstruction *, GArchOperand *);
+/* Remplace un opérande d'une instruction par un autre. */
+bool g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
-/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */
+/* Détache un opérande liée d'une instruction. */
+bool g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
+/* Fournit un opérande donné d'une instruction. */
+GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *, size_t);
+
+/* Détermine le chemin conduisant à un opérande. */
+char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *);
+
+
+
+
+#if 0
+
+
+
+/**
+ * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut
+ * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références
+ * circulaires.
+ *
+ * On procède donc à une seconde déclaration, en attendant éventuellement mieux.
+ */
+
+/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
+typedef struct _GArchProcessor GArchProcessor;
+
+
+/* Complète un désassemblage accompli pour une instruction. */
+typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *);
+
+/* Complète un désassemblage accompli pour une instruction. */
+void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
-/* Fournit le nom humain de l'instruction manipulée. */
-const char *g_arch_instruction_get_keyword(GArchInstruction *);
-/* Construit un petit résumé concis de l'instruction. */
-char *g_arch_instruction_build_tooltip(const GArchInstruction *);
-/* Fournit une description pour l'instruction manipulée. */
-const char *g_arch_instruction_get_description(const GArchInstruction *);
+#endif
diff --git a/src/arch/instructions/Makefile.am b/src/arch/instructions/Makefile.am
index 28cf90f..d6fc4bd 100644
--- a/src/arch/instructions/Makefile.am
+++ b/src/arch/instructions/Makefile.am
@@ -1,12 +1,19 @@
-noinst_LTLIBRARIES = libarchinstructions.la
+noinst_LTLIBRARIES = libarchinstructions.la libarchinstructionsui.la
libarchinstructions_la_SOURCES = \
+ raw-int.h \
raw.h raw.c \
undefined-int.h \
undefined.h undefined.c
-libarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+libarchinstructions_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+libarchinstructionsui_la_SOURCES = \
+ raw-ui.h raw-ui.c \
+ undefined-ui.h undefined-ui.c
+
+libarchinstructionsui_la_CFLAGS = $(LIBGTK4_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
diff --git a/src/arch/instructions/raw-int.h b/src/arch/instructions/raw-int.h
new file mode 100644
index 0000000..4a5e64b
--- /dev/null
+++ b/src/arch/instructions/raw-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * raw-int.h - prototypes pour la définition interne des instructions de données brutes
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRUCTIONS_RAW_INT_H
+#define _ARCH_INSTRUCTIONS_RAW_INT_H
+
+
+#include "raw.h"
+#include "../instruction-int.h"
+
+
+
+/* Définition générique d'une instruction brute d'architecture (instance) */
+struct _GRawInstruction
+{
+ GArchInstruction parent; /* A laisser en premier */
+
+};
+
+/* Définition générique d'une instruction brute d'architecture (instance) */
+struct _GRawInstructionClass
+{
+ GArchInstructionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une instruction de type 'db/dw/etc' simple. */
+bool g_raw_instruction_create_value(GRawInstruction *, GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t);
+
+/* Met en place une instruction de type 'db/dw/etc' étendue. */
+bool g_raw_instruction_create_array(GRawInstruction *, GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian);
+
+
+
+#endif /* _ARCH_INSTRUCTIONS_RAW_INT_H */
diff --git a/src/arch/instructions/raw-ui.c b/src/arch/instructions/raw-ui.c
new file mode 100644
index 0000000..1026dfb
--- /dev/null
+++ b/src/arch/instructions/raw-ui.c
@@ -0,0 +1,261 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * raw-ui.c - opérandes représentant des instructions de données brutes sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "raw-ui.h"
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <malloc.h>
+
+
+#include "raw.h"
+#include "../operand-ui.h"
+#include "../operands/immediate.h"
+#include "../../glibext/objhole.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_raw_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface)
+{
+ iface->populate = g_raw_instruction_ui_populate_line;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à utiliser pour l'impression. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* line = ligne de rendu à compléter. *
+* data = éventuelle donnée complémentaire fournie. *
+* *
+* Description : Etablit dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_raw_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+ GArchInstruction *instr; /* Version spécialisée #1 */
+ GRawInstruction *raw; /* Version spécialisée #2 */
+ GBinContent *content; /* Contenu brut d'origine */
+ mrange_t range; /* Emplacement couvert */
+ phys_t max_displayed_len; /* Quantité de code affichée */
+ char *key; /* Mot clef principal */
+ char *string; /* Chaîne reconstituée */
+ size_t iter; /* Tête d'écriture */
+ bool first; /* Mémorise une énumération */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ GImmediateOperand *imm; /* Version opérande de valeur */
+ char byte; /* Octet à afficher (ou pas) */
+#ifndef NDEBUG
+ bool status; /* Bilan d'une récupération */
+#endif
+
+ instr = G_ARCH_INSTRUCTION(generator);
+ raw = G_RAW_INSTRUCTION(instr);
+ content = G_BIN_CONTENT(data);
+
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ /* Prologue */
+
+ if (g_arch_instruction_get_range(instr, &range))
+ {
+ /* Localisation */
+
+ g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ /* Contenu */
+
+ if (g_raw_instruction_is_padding(raw))
+ max_displayed_len = 0;
+
+ else if (g_raw_instruction_is_string(raw))
+ max_displayed_len = 1;
+
+ else
+ {
+ max_displayed_len = get_mrange_length(&range);
+ max_displayed_len /= g_arch_instruction_count_operands(instr);
+ }
+
+ g_buffer_line_fill_content(line, ACO_BINARY, content, &range, max_displayed_len);
+
+ }
+
+ /* Instruction proprement dite */
+
+ key = g_arch_instruction_get_keyword(instr);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr));
+
+ free(key);
+
+ /* Contenu sous forme d'opérandes */
+
+ if (g_raw_instruction_is_padding(raw))
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL("..."), NULL, NULL);
+
+ else
+ {
+ string = NULL;
+ iter = 0;
+
+ first = true;
+
+ count = g_arch_instruction_count_operands(instr);
+
+ for (i = 0; i < count; i++)
+ {
+ op = g_arch_instruction_get_operand(instr, i);
+
+ if (!G_IS_IMMEDIATE_OPERAND(op))
+ goto fallback;
+
+ imm = G_IMMEDIATE_OPERAND(op);
+
+ if (g_immediate_operand_get_size(imm) != MDS_8_BITS)
+ goto fallback;
+
+ if (!g_raw_instruction_is_string(raw) && g_immediate_operand_get_display(imm) != IOD_CHAR)
+ goto fallback;
+
+#ifndef NDEBUG
+ status = g_immediate_operand_get_value(imm, MDS_8_BITS, &byte);
+ assert(status);
+#else
+ g_immediate_operand_get_value(imm, MDS_8_BITS, &byte);
+#endif
+
+ /* Si le caractère doit apparaître en hexadécimal... */
+
+ if (!isprint(byte))
+ goto fallback;
+
+ /* Impression de l'octet */
+
+ if (string == NULL)
+ {
+ string = calloc(count + 3, sizeof(char));
+
+ strcpy(string, "\"");
+ iter = 1;
+
+ }
+
+ string[iter++] = byte;
+
+ unref_object(op);
+
+ continue;
+
+ fallback:
+
+ /* Si une chaîne précède */
+
+ if (string != NULL && iter > 1)
+ {
+ if (!first)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL);
+ }
+ else
+ first = false;
+
+ string[iter++] = '"';
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL);
+
+ iter = 1;
+
+ }
+
+ /* Intégration en tant qu'opérande classique */
+
+ if (!first)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL);
+ }
+ else
+ first = false;
+
+ g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line);
+
+ unref_object(op);
+
+ }
+
+ /* Si au final une chaîne traine encore */
+
+ if (string != NULL && iter > 1)
+ {
+ if (!first)
+ {
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL);
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL);
+ }
+
+ string[iter++] = '"';
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL);
+
+ }
+
+ if (string != NULL)
+ free(string);
+
+ }
+
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
+
+}
diff --git a/src/arch/instructions/raw-ui.h b/src/arch/instructions/raw-ui.h
new file mode 100644
index 0000000..cd604e6
--- /dev/null
+++ b/src/arch/instructions/raw-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * raw-ui.h - prototypes pour les opérandes représentant des instructions de données brutes sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_RAW_UI_H
+#define _ARCH_OPERANDS_RAW_UI_H
+
+
+#include "../../glibext/generator-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_RAW_UI_H */
diff --git a/src/arch/instructions/raw.c b/src/arch/instructions/raw.c
index 26282fa..87297f1 100644
--- a/src/arch/instructions/raw.c
+++ b/src/arch/instructions/raw.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* raw.c - instructions pures vues de l'esprit
*
- * Copyright (C) 2014-2020 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,36 +25,19 @@
#include <assert.h>
-#include <ctype.h>
#include <string.h>
#include <i18n.h>
-#include "../instruction-int.h"
+#include "raw-int.h"
#include "../operands/immediate.h"
-#include "../operands/target.h"
-#include "../../core/columns.h"
+//#include "../operands/target.h" // FIXME
-/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */
-
-
-/* Définition générique d'une instruction brute d'architecture (instance) */
-struct _GRawInstruction
-{
- GArchInstruction parent; /* A laisser en premier */
-
-};
-
-/* Définition générique d'une instruction brute d'architecture (classe) */
-struct _GRawInstructionClass
-{
- GArchInstructionClass parent; /* A laisser en premier */
-
-};
+/* --------------------- INSTRUCTION AVEC JEU DE DONNEES BRUTES --------------------- */
/* Initialise la classe des instructions brutes d'architecture. */
@@ -64,40 +47,26 @@ static void g_raw_instruction_class_init(GRawInstructionClass *);
static void g_raw_instruction_init(GRawInstruction *);
/* Supprime toutes les références externes. */
-static void g_raw_instruction_dispose(GRawInstruction *);
+static void g_raw_instruction_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_raw_instruction_finalize(GRawInstruction *);
-
-/* Indique l'encodage d'une instruction de façon détaillée. */
-static const char *g_raw_instruction_get_encoding(const GRawInstruction *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static const char *g_raw_instruction_get_keyword(const GRawInstruction *);
+static void g_raw_instruction_finalize(GObject *);
-/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Charge une instruction depuis une mémoire tampon. */
-static bool g_raw_instruction_unserialize(GRawInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde une instruction dans une mémoire tampon. */
-static bool g_raw_instruction_serialize(GRawInstruction *, GAsmStorage *, packed_buffer_t *);
-
-
-
-/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
-
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static char *g_raw_instruction_get_encoding(const GArchInstruction *);
-/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
-static void g_raw_instruction_print(GRawInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
+/* Fournit le nom humain de l'instruction manipulée. */
+static char *g_raw_instruction_get_keyword(const GArchInstruction *);
/* ---------------------------------------------------------------------------------- */
-/* INSTRUCTION INCONNUE / DONNEES */
+/* INSTRUCTION AVEC JEU DE DONNEES BRUTES */
/* ---------------------------------------------------------------------------------- */
@@ -124,18 +93,13 @@ static void g_raw_instruction_class_init(GRawInstructionClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_raw_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_raw_instruction_finalize;
+ object->dispose = g_raw_instruction_dispose;
+ object->finalize = g_raw_instruction_finalize;
instr = G_ARCH_INSTRUCTION_CLASS(klass);
- instr->get_encoding = (get_instruction_encoding_fc)g_raw_instruction_get_encoding;
- instr->get_keyword = (get_instruction_keyword_fc)g_raw_instruction_get_keyword;
-
- instr->unserialize = (unserialize_instruction_fc)g_raw_instruction_unserialize;
- instr->serialize = (serialize_instruction_fc)g_raw_instruction_serialize;
-
- instr->print = (print_instruction_fc)g_raw_instruction_print;
+ instr->get_encoding = g_raw_instruction_get_encoding;
+ instr->get_keyword = g_raw_instruction_get_keyword;
}
@@ -160,7 +124,7 @@ static void g_raw_instruction_init(GRawInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -170,16 +134,16 @@ static void g_raw_instruction_init(GRawInstruction *instr)
* *
******************************************************************************/
-static void g_raw_instruction_dispose(GRawInstruction *instr)
+static void g_raw_instruction_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -189,16 +153,17 @@ static void g_raw_instruction_dispose(GRawInstruction *instr)
* *
******************************************************************************/
-static void g_raw_instruction_finalize(GRawInstruction *instr)
+static void g_raw_instruction_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(object);
}
/******************************************************************************
* *
-* Paramètres : addr = position à associer à l'instruction. *
+* Paramètres : area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
* size = taille de l'opérande souhaitée. *
* value = valeur sur x bits à venir récupérer. *
* *
@@ -210,127 +175,106 @@ static void g_raw_instruction_finalize(GRawInstruction *instr)
* *
******************************************************************************/
-GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *addr, MemoryDataSize size, uint64_t value)
+GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value)
{
GArchInstruction *result; /* Instruction à retourner */
- GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
- operand = g_imm_operand_new_from_value(size, value);
- if (operand == NULL) goto error;
+ if (!g_raw_instruction_create_value(G_RAW_INSTRUCTION(result), area, addr, size, value))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instance à initialiser pleinement. *
+* area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
+* size = taille de chacun des éléments à représenter. *
+* value = valeur sur x bits à venir récupérer. *
+* *
+* Description : Met en place une instruction de type 'db/dw/etc' simple. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_raw_instruction_create_value(GRawInstruction *instr, GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value)
+{
+ bool result; /* Bilan à retourner */
+ GArchOperand *operand; /* Octet non décodé à afficher */
+ uint16_t length; /* Taille de l'instruction */
+
+ result = false;
+
+ operand = g_immediate_operand_new_from_value(size, value);
+ if (operand == NULL) goto exit;
g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
- g_arch_instruction_attach_extra_operand(result, operand);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
+
+ g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand);
+ unref_object(operand);
+
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
switch (size)
{
case MDS_8_BITS_UNSIGNED:
case MDS_8_BITS_SIGNED:
- init_mrange(&range, addr, 1);
+ length = 1;
break;
case MDS_16_BITS_UNSIGNED:
case MDS_16_BITS_SIGNED:
- init_mrange(&range, addr, 2);
+ length = 2;
break;
case MDS_32_BITS_UNSIGNED:
case MDS_32_BITS_SIGNED:
- init_mrange(&range, addr, 4);
+ length = 4;
break;
case MDS_64_BITS_UNSIGNED:
case MDS_64_BITS_SIGNED:
- init_mrange(&range, addr, 8);
+ length = 8;
break;
default:
assert(false);
- goto error;
+ goto exit;
break;
}
- g_arch_instruction_set_range(result, &range);
+ g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, addr, length);
- return result;
-
- error:
-
- g_object_unref(G_OBJECT(result));
-
- return NULL;
-
-}
+ result = true;
-
-/******************************************************************************
-* *
-* Paramètres : content = flux de données à analyser. *
-* addr = position courante dans ce flux. [OUT] *
-* *
-* Description : Crée une instruction de type 'db/dw/etc' pour un uleb128. *
-* *
-* Retour : Instruction mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *addr)
-{
- GArchInstruction *result; /* Instruction à retourner */
- vmpa2t start; /* Départ original de lecture */
- uleb128_t value; /* Valeur uleb128 à représenter*/
- phys_t diff; /* Couverture de la lecture */
- MemoryDataSize leb_size; /* Taille de la valeur */
- GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
-
- result = NULL;
-
- copy_vmpa(&start, addr);
-
- if (!g_binary_content_read_uleb128(content, addr, &value))
- goto error;
-
- diff = compute_vmpa_diff(&start, addr);
-
- leb_size = MDS_FROM_BYTES(diff);
- assert(leb_size != MDS_UNDEFINED);
-
- result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
-
- init_mrange(&range, &start, diff);
- g_arch_instruction_set_range(result, &range);
-
- operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value);
- if (operand == NULL) goto error;
-
- g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
-
- g_arch_instruction_attach_extra_operand(result, operand);
+ exit:
return result;
- error:
-
- g_clear_object(&result);
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : content = flux de données à analyser. *
-* addr = position courante dans ce flux. [OUT] *
+* Paramètres : area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
+* size = taille de chacun des éléments à représenter. *
+* content = flux de données à analyser. *
+* count = nombre de ces éléments. *
+* endian = ordre des bits dans la source. *
* *
-* Description : Crée une instruction de type 'db/dw/etc' pour un sleb128. *
+* Description : Crée une instruction de type 'db/dw/etc' étendue. *
* *
* Retour : Instruction mise en place. *
* *
@@ -338,256 +282,174 @@ GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa
* *
******************************************************************************/
-GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *addr)
+GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian)
{
GArchInstruction *result; /* Instruction à retourner */
- vmpa2t start; /* Départ original de lecture */
- uleb128_t value; /* Valeur uleb128 à représenter*/
- phys_t diff; /* Couverture de la lecture */
- MemoryDataSize leb_size; /* Taille de la valeur */
- GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
-
- result = NULL;
-
- copy_vmpa(&start, addr);
-
- if (!g_binary_content_read_uleb128(content, addr, &value))
- goto error;
-
- diff = compute_vmpa_diff(&start, addr);
-
- leb_size = MDS_FROM_BYTES(diff) | MDS_SIGN;
- assert(leb_size != MDS_SIGN);
result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
- init_mrange(&range, &start, diff);
- g_arch_instruction_set_range(result, &range);
-
- operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value);
- if (operand == NULL) goto error;
-
- g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
-
- g_arch_instruction_attach_extra_operand(result, operand);
+ if (!g_raw_instruction_create_array(G_RAW_INSTRUCTION(result), area, addr, size, content, count, endian))
+ g_clear_object(&result);
return result;
- error:
-
- g_clear_object(&result);
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : content = flux de données à analyser. *
+* Paramètres : instr = instance à initialiser pleinement. *
+* area = portion de binaire incluant l'instruction. *
+* addr = adresse virtuelle et/ou position physique. *
* size = taille de chacun des éléments à représenter. *
+* content = flux de données à analyser. *
* count = nombre de ces éléments. *
-* addr = position courante dans ce flux. [OUT] *
* endian = ordre des bits dans la source. *
* *
-* Description : Crée une instruction de type 'db/dw/etc' étendue. *
+* Description : Met en place une instruction de type 'db/dw/etc' étendue. *
* *
-* Retour : Instruction mise en place. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchInstruction *g_raw_instruction_new_array(const GBinContent *content, MemoryDataSize size, size_t count, vmpa2t *addr, SourceEndian endian)
+bool g_raw_instruction_create_array(GRawInstruction *instr, GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian)
{
- GArchInstruction *result; /* Instruction à retourner */
- vmpa2t old; /* Sauvegarde de la position */
+ bool result; /* Bilan à retourner */
+ vmpa2t start; /* Sauvegarde de la position */
size_t i; /* Boucle de parcours */
GArchOperand *operand; /* Octet non décodé à afficher */
- mrange_t range; /* Couverture de l'instruction */
+ phys_t diff; /* Décalage à appliquer */
+
+ result = false;
/* Par soucis de cohérence */
- if (count == 0) return NULL;
+ if (count == 0)
+ goto exit;
- result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
+ copy_vmpa(&start, addr);
- copy_vmpa(&old, addr);
+ g_thick_object_lock(G_THICK_OBJECT(instr));
for (i = 0; i < count; i++)
{
- operand = g_imm_operand_new_from_data(size, content, addr, endian);
- if (operand == NULL) goto error;
+ operand = g_immediate_operand_new_from_data(size, content, addr, (bool []){ false /* unused */ }, endian);
+ if (operand == NULL) break;
g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING);
- g_arch_instruction_attach_extra_operand(result, operand);
+ g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand);
+ unref_object(operand);
}
- init_mrange(&range, &old, compute_vmpa_diff(addr, &old));
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- g_arch_instruction_set_range(result, &range);
+ if (i < count)
+ goto exit;
- return result;
+ diff = compute_vmpa_diff(addr, &start);
+
+ g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, &start, diff);
- error:
+ result = true;
- g_object_unref(G_OBJECT(result));
+ exit:
- return NULL;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
+* Paramètres : instr = instruction à traiter. *
+* is_padding = nouveau statut à associer au contenu. *
* *
-* Description : Indique l'encodage d'une instruction de façon détaillée. *
+* Description : Marque l'instruction comme ne contenant que du bourrage. *
* *
-* Retour : Description humaine de l'encodage utilisé. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static const char *g_raw_instruction_get_encoding(const GRawInstruction *instr)
+void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding)
{
- const char *result; /* Description à retourner */
-
- if (g_raw_instruction_is_string(instr))
- result = _("String");
+ if (is_padding)
+ g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
else
- result = _("Raw");
-
- return result;
+ g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
}
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
+* Paramètres : instr = instruction à traiter. *
+* is_padding = nouveau statut à associer au contenu. *
* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
+* Description : Indique si le contenu de l'instruction est du bourrage. *
* *
-* Retour : Mot clef de bas niveau. *
+* Retour : Statut du contenu de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr)
+bool g_raw_instruction_is_padding(const GRawInstruction *instr)
{
- GArchOperand *operand; /* Octet décodé à afficher */
- MemoryDataSize size; /* Taille de valeur associée */
-
- static char *defines[] = { "dn", "db", "dw", "dd", "dq" };
-
- operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 0);
-
- if (G_IS_TARGET_OPERAND(operand))
- size = g_target_operand_get_size(G_TARGET_OPERAND(operand));
- else
- size = g_imm_operand_get_size(G_IMM_OPERAND(operand));
+ bool result; /* Indication à retourner */
- g_object_unref(G_OBJECT(operand));
+ result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
- return defines[MDS_RANGE(size)];
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction à traiter. *
+* is_string = nouveau statut à associer au contenu. *
* *
-* Description : Charge une instruction depuis une mémoire tampon. *
+* Description : Marque l'instruction comme contenant une chaîne de texte. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_raw_instruction_unserialize(GRawInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class);
-
- result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf);
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- g_raw_instruction_mark_as_padding(instr, (boolean == 1));
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- g_raw_instruction_mark_as_string(instr, (boolean == 1));
-
- }
-
- return result;
+ if (is_string)
+ g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
+ else
+ g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
}
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction à traiter. *
+* is_string = nouveau statut à associer au contenu. *
* *
-* Description : Sauvegarde une instruction dans une mémoire tampon. *
+* Description : Indique si le contenu de l'instruction est un texte. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Statut du contenu de l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf)
+bool g_raw_instruction_is_string(const GRawInstruction *instr)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class);
-
- result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf);
-
- if (result)
- {
- boolean = (g_raw_instruction_is_padding(instr) ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ bool result; /* Indication à retourner */
- if (result)
- {
- boolean = (g_raw_instruction_is_string(instr) ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
return result;
@@ -596,285 +458,73 @@ static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *sto
/* ---------------------------------------------------------------------------------- */
-/* OFFRE DE CAPACITES DE GENERATION */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : instr = instruction d'assemblage à représenter. *
-* line = ligne de rendu à compléter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* content = éventuel contenu binaire brut à imprimer. *
+* Paramètres : instr = instruction quelconque à consulter. *
* *
-* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : - *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
+static char *g_raw_instruction_get_encoding(const GArchInstruction *instr)
{
- GArchInstruction *base; /* Autre version de l'instance */
- phys_t max_displayed_len; /* Quantité de code affichée */
- const char *key; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
- char *string; /* Chaîne reconstituée */
- size_t iter; /* Tête d'écriture */
- bool first; /* Mémorise une énumération */
- size_t count; /* Nombre d'opérandes en place */
- size_t i; /* Boucle de parcours */
- GArchOperand *op; /* Opérande à manipuler */
- GImmOperand *imm; /* Version opérande de valeur */
- char byte; /* Octet à afficher (ou pas) */
-#ifndef NDEBUG
- bool status; /* Bilan d'une récupération */
-#endif
-
- base = G_ARCH_INSTRUCTION(instr);
-
- /* Localisation */
-
- g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- /* Contenu */
-
- if (g_raw_instruction_is_padding(instr))
- max_displayed_len = 0;
-
- else if (g_raw_instruction_is_string(instr))
- max_displayed_len = 1;
-
- else
- {
- max_displayed_len = get_mrange_length(&base->range);
- max_displayed_len /= g_arch_instruction_count_operands(base);
- }
-
- g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, max_displayed_len);
-
- /* Zone du code d'assemblage */
+ char *result; /* Description à retourner */
+ GRawInstruction *raw; /* Version spécialisée */
- key = g_arch_instruction_get_keyword(base);
- klen = strlen(key);
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL);
-
- if (g_raw_instruction_is_padding(instr))
- g_buffer_line_append_text(line, DLC_ASSEMBLY, "...", 3, RTT_RAW, NULL);
+ raw = G_RAW_INSTRUCTION(instr);
+ if (g_raw_instruction_is_string(raw))
+ result = strdup(_("String"));
else
- {
- string = NULL;
- iter = 0;
-
- first = true;
-
- g_arch_instruction_lock_operands(base);
-
- count = _g_arch_instruction_count_operands(base);
-
- for (i = 0; i < count; i++)
- {
- op = _g_arch_instruction_get_operand(base, i);
-
- if (!G_IS_IMM_OPERAND(op))
- goto grip_fallback;
-
- imm = G_IMM_OPERAND(op);
-
- if (g_imm_operand_get_size(imm) != MDS_8_BITS)
- goto grip_fallback;
-
- if (!g_raw_instruction_is_string(instr) && g_imm_operand_get_display(imm) != IOD_CHAR)
- goto grip_fallback;
-
-#ifndef NDEBUG
- status = g_imm_operand_get_value(imm, MDS_8_BITS, &byte);
- assert(status);
-#else
- g_imm_operand_get_value(imm, MDS_8_BITS, &byte);
-#endif
-
- /* Si le caractère doit apparaître en hexadécimal... */
-
- if (!isprint(byte))
- goto grip_fallback;
-
- /* Impression de l'octet */
-
- if (string == NULL)
- {
- string = (char *)calloc(count + 3, sizeof(char));
-
- strcpy(string, "\"");
- iter = 1;
-
- }
-
- string[iter++] = byte;
-
- g_object_unref(G_OBJECT(op));
-
- continue;
-
- grip_fallback:
-
- /* Si une chaîne précède */
-
- if (string != NULL && iter > 1)
- {
- if (!first)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
- else
- first = false;
-
- string[iter++] = '"';
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL);
-
- iter = 1;
-
- }
-
- /* Intégration en tant qu'opérande classique */
-
- if (!first)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
- else
- first = false;
-
- g_arch_operand_print(op, line);
-
- g_object_unref(G_OBJECT(op));
-
- }
-
- /* Si au final une chaîne traine encore */
-
- if (string != NULL && iter > 1)
- {
- if (!first)
- {
- g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
- }
-
- string[iter++] = '"';
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL);
-
- }
+ result = strdup(_("Raw"));
- g_arch_instruction_unlock_operands(base);
-
- if (string != NULL)
- free(string);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à traiter. *
-* is_padding = nouveau statut à associer au contenu. *
-* *
-* Description : Marque l'instruction comme ne contenant que du bourrage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding)
-{
- if (is_padding)
- g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
- else
- g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction à traiter. *
-* is_padding = nouveau statut à associer au contenu. *
+* Paramètres : instr = instruction d'assemblage à consulter. *
* *
-* Description : Indique si le contenu de l'instruction est du bourrage. *
+* Description : Fournit le nom humain de l'instruction manipulée. *
* *
-* Retour : Statut du contenu de l'instruction. *
+* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_raw_instruction_is_padding(const GRawInstruction *instr)
+static char *g_raw_instruction_get_keyword(const GArchInstruction *instr)
{
- bool result; /* Indication à retourner */
-
- result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING);
-
- return result;
-
-}
+ char *result; /* Désignation à retourner */
+ GArchOperand *operand; /* Octet décodé à afficher */
+ MemoryDataSize size; /* Taille de valeur associée */
+ static char *defines[] = { "dn", "db", "dw", "dd", "dq" };
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à traiter. *
-* is_string = nouveau statut à associer au contenu. *
-* *
-* Description : Marque l'instruction comme contenant une chaîne de texte. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ g_thick_object_lock(G_THICK_OBJECT(instr));
-void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string)
-{
- if (is_string)
- g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
- else
- g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
-
-}
+ operand = g_arch_instruction_get_operand(instr, 0);
+ /*if (G_IS_TARGET_OPERAND(operand)) FIXME
+ size = g_target_operand_get_size(G_TARGET_OPERAND(operand));
+ else*/
+ size = g_immediate_operand_get_size(G_IMMEDIATE_OPERAND(operand));
-/******************************************************************************
-* *
-* Paramètres : instr = instruction à traiter. *
-* is_string = nouveau statut à associer au contenu. *
-* *
-* Description : Indique si le contenu de l'instruction est un texte. *
-* *
-* Retour : Statut du contenu de l'instruction. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ unref_object(operand);
-bool g_raw_instruction_is_string(const GRawInstruction *instr)
-{
- bool result; /* Indication à retourner */
+ g_thick_object_unlock(G_THICK_OBJECT(instr));
- result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING);
+ result = strdup(defines[MDS_RANGE(size)]);
return result;
diff --git a/src/arch/instructions/raw.h b/src/arch/instructions/raw.h
index 4e92cd4..712f877 100644
--- a/src/arch/instructions/raw.h
+++ b/src/arch/instructions/raw.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * raw.h - prototypes pour les instructions pures vues de l'esprit
+ * raw.h - prototypes pour les instructions de données brutes
*
- * Copyright (C) 2014-2020 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,46 +25,24 @@
#define _ARCH_INSTRUCTIONS_RAW_H
-#include <glib-object.h>
-
-
#include "../instruction.h"
#include "../vmpa.h"
+#include "../../analysis/content.h"
+#include "../../glibext/helpers.h"
-/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */
-
-
-#define G_TYPE_RAW_INSTRUCTION g_raw_instruction_get_type()
-#define G_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RAW_INSTRUCTION, GRawInstruction))
-#define G_IS_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RAW_INSTRUCTION))
-#define G_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass))
-#define G_IS_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RAW_INSTRUCTION))
-#define G_RAW_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass))
-
+#define G_TYPE_RAW_INSTRUCTION (g_raw_instruction_get_type())
-/* Définition générique d'une instruction brute d'architecture (instance) */
-typedef struct _GRawInstruction GRawInstruction;
+DECLARE_GTYPE(GRawInstruction, g_raw_instruction, G, RAW_INSTRUCTION);
-/* Définition générique d'une instruction brute d'architecture (classe) */
-typedef struct _GRawInstructionClass GRawInstructionClass;
-
-
-/* Indique le type défini pour une instruction inconnue d'architecture. */
-GType g_raw_instruction_get_type(void);
/* Crée une instruction de type 'db/dw/etc' simple. */
-GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *, MemoryDataSize, uint64_t);
+GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t);
-/* Crée une instruction de type 'db/dw/etc' pour un uleb128. */
-GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *);
+/* Crée une instruction de type 'db/dw/etc' étendue. */
+GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian);
-/* Crée une instruction de type 'db/dw/etc' pour un sleb128. */
-GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *);
-
-/* Crée une instruction de type 'db/dw/etc' étendue. */
-GArchInstruction *g_raw_instruction_new_array(const GBinContent *, MemoryDataSize, size_t, vmpa2t *, SourceEndian);
/* Drapeaux pour informations complémentaires */
typedef enum _RawInstrFlag
@@ -74,6 +52,7 @@ typedef enum _RawInstrFlag
} RawInstrFlag;
+
/* Marque l'instruction comme ne contenant que du bourrage. */
void g_raw_instruction_mark_as_padding(GRawInstruction *, bool);
diff --git a/src/arch/instructions/undefined-int.h b/src/arch/instructions/undefined-int.h
index a9b7627..faf0b4b 100644
--- a/src/arch/instructions/undefined-int.h
+++ b/src/arch/instructions/undefined-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * undefined-int.h - prototypes pour la définition générique interne des instructions au comportement non défini
+ * undefined-int.h - prototypes pour la définition interne des instructions au comportement non défini
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -27,42 +27,18 @@
#include "undefined.h"
#include "../instruction-int.h"
-#include "../../glibext/objhole.h"
-/* Informations glissées dans la structure GObject de GArchInstruction */
-typedef struct _undef_extra_data_t
-{
- /**
- * Le champ uid de la structure parente attendue conduit à une taille
- * alignée sur 2 octets, donc à une taille totale de 4 octets ce qui
- * représente la limite maximale de taille supportée.
- *
- * Pour 3 octets à la base, qui devraient laisser 8 - 1 octets disponbibles
- * en incluant le bit de verrouillage.
- *
- * On reproduit donc la structure instr_extra_data_t ici, en basculant
- * l'énumération InstrExpectedBehavior en champ de bits.
- */
-
- itid_t uid; /* Identifiant unique du type */
- ArchInstrFlag flags; /* Informations complémentaires*/
-
- unsigned int behavior : 2; /* Conséquences réelles */
-
-} undef_extra_data_t;
-
-
/* Définition générique d'une instruction au comportement non défini (instance) */
-struct _GUndefInstruction
+struct _GUndefinedInstruction
{
GArchInstruction parent; /* A laisser en premier */
};
/* Définition générique d'une instruction au comportement non défini (classe) */
-struct _GUndefInstructionClass
+struct _GUndefinedInstructionClass
{
GArchInstructionClass parent; /* A laisser en premier */
@@ -73,15 +49,25 @@ struct _GUndefInstructionClass
* Accès aux informations éventuellement déportées.
*/
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+/* Informations glissées dans la structure GObject de GArchInstruction */
+typedef struct _undef_extra_data_t
+{
+ ARCH_INSTRUCTION_EXTRA_DATA
+
+ unsigned int behavior : 2; /* Conséquences réelles */
+
+} undef_extra_data_t;
+
-# define GET_UNDEF_INSTR_EXTRA(ins) ((undef_extra_data_t *)&((GArchInstruction *)ins)->extra)
+#define GET_UNDEF_INSTR_EXTRA(op) \
+ GET_GOBJECT_EXTRA(op, undef_extra_data_t)
-#else
+#define SET_UNDEF_INSTR_EXTRA(op, data) \
+ SET_GOBJECT_EXTRA(op, undef_extra_data_t, data)
-# define GET_UNDEF_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), undef_extra_data_t)
-#endif
+/* Met en place une instruction au comportement indéfini. */
+bool g_undefined_instruction_create(GUndefinedInstruction *, InstrExpectedBehavior);
diff --git a/src/arch/instructions/undefined-ui.c b/src/arch/instructions/undefined-ui.c
new file mode 100644
index 0000000..fbc0452
--- /dev/null
+++ b/src/arch/instructions/undefined-ui.c
@@ -0,0 +1,102 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * undefined-ui.c - opérandes représentant des instructions indéfinies sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "undefined-ui.h"
+
+
+#include "../instruction.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Etablit dans une ligne de rendu le contenu représenté. */
+static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface)
+{
+ iface->populate = g_undefined_instruction_ui_populate_line;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : generator = générateur à utiliser pour l'impression. *
+* index = indice de cette même ligne dans le tampon global.*
+* repeat = indice d'utilisations successives du générateur. *
+* line = ligne de rendu à compléter. *
+* data = éventuelle donnée complémentaire fournie. *
+* *
+* Description : Etablit dans une ligne de rendu le contenu représenté. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data)
+{
+ GArchInstruction *instr; /* Version spécialisée */
+ GBinContent *content; /* Contenu brut d'origine */
+ mrange_t range; /* Emplacement couvert */
+ char *key; /* Mot clef principal */
+
+ instr = G_ARCH_INSTRUCTION(generator);
+ content = G_BIN_CONTENT(data);
+
+ /* Prologue */
+
+ if (g_arch_instruction_get_range(instr, &range))
+ {
+ g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range));
+
+ g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL);
+
+ }
+
+ /* Instruction proprement dite */
+
+ key = g_arch_instruction_get_keyword(instr);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_ERROR, SL(key), NULL, G_OBJECT(instr));
+
+ free(key);
+
+}
diff --git a/src/arch/instructions/undefined-ui.h b/src/arch/instructions/undefined-ui.h
new file mode 100644
index 0000000..8bc2d67
--- /dev/null
+++ b/src/arch/instructions/undefined-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * undefined-ui.h - prototypes pour les opérandes représentant des instructions indéfinies sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_UNDEFINED_UI_H
+#define _ARCH_OPERANDS_UNDEFINED_UI_H
+
+
+#include "../../glibext/generator-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_UNDEFINED_UI_H */
diff --git a/src/arch/instructions/undefined.c b/src/arch/instructions/undefined.c
index 15c63e7..75df493 100644
--- a/src/arch/instructions/undefined.c
+++ b/src/arch/instructions/undefined.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* undefined.c - instructions au comportement non défini
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,63 +25,42 @@
#include <assert.h>
+#include <string.h>
#include <i18n.h>
#include "undefined-int.h"
-#include "../../core/columns.h"
+#include "../../glibext/serialize-int.h"
+/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */
+
+
/* Initialise la classe des instructions non définies. */
-static void g_undef_instruction_class_init(GUndefInstructionClass *);
+static void g_undefined_instruction_class_init(GUndefinedInstructionClass *);
/* Initialise une instance d'instruction non définie. */
-static void g_undef_instruction_init(GUndefInstruction *);
+static void g_undefined_instruction_init(GUndefinedInstruction *);
/* Supprime toutes les références externes. */
-static void g_undef_instruction_dispose(GUndefInstruction *);
+static void g_undefined_instruction_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_undef_instruction_finalize(GUndefInstruction *);
-
-/* Indique l'encodage d'une instruction de façon détaillée. */
-static const char *g_undef_instruction_get_encoding(const GUndefInstruction *);
-
-/* Fournit le nom humain de l'instruction manipulée. */
-static const char *g_undef_instruction_get_keyword(const GUndefInstruction *);
-
-
-
-/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */
-
-
-/* Charge une instruction depuis une mémoire tampon. */
-static bool g_undef_instruction_unserialize(GUndefInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde une instruction dans une mémoire tampon. */
-static bool g_undef_instruction_serialize(GUndefInstruction *, GAsmStorage *, packed_buffer_t *);
-
-
-
-/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
-
-
-/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
-static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
+static void g_undefined_instruction_finalize(GObject *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_undef_instruction_load(GUndefInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static char *g_undefined_instruction_get_encoding(const GArchInstruction *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, packed_buffer_t *);
+/* Fournit le nom humain de l'instruction manipulée. */
+static char *g_undefined_instruction_get_keyword(const GArchInstruction *);
@@ -91,7 +70,9 @@ static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, pac
/* Indique le type défini pour une instruction au comportement non défini. */
-G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION);
+G_DEFINE_TYPE_WITH_CODE(GUndefinedInstruction, g_undefined_instruction, G_TYPE_ARCH_INSTRUCTION,
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_undefined_instruction_ui_token_generator_iface_init));
+
/******************************************************************************
@@ -106,28 +87,20 @@ G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION);
* *
******************************************************************************/
-static void g_undef_instruction_class_init(GUndefInstructionClass *klass)
+static void g_undefined_instruction_class_init(GUndefinedInstructionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GArchInstructionClass *instr; /* Encore une autre vision... */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_undef_instruction_dispose;
- object->finalize = (GObjectFinalizeFunc)g_undef_instruction_finalize;
+ object->dispose = g_undefined_instruction_dispose;
+ object->finalize = g_undefined_instruction_finalize;
instr = G_ARCH_INSTRUCTION_CLASS(klass);
- instr->get_encoding = (get_instruction_encoding_fc)g_undef_instruction_get_encoding;
- instr->get_keyword = (get_instruction_keyword_fc)g_undef_instruction_get_keyword;
-
- instr->unserialize = (unserialize_instruction_fc)g_undef_instruction_unserialize;
- instr->serialize = (serialize_instruction_fc)g_undef_instruction_serialize;
-
- instr->print = (print_instruction_fc)g_undef_instruction_print;
-
- instr->load = (load_instruction_fc)g_undef_instruction_load;
- instr->store = (store_instruction_fc)g_undef_instruction_store;
+ instr->get_encoding = g_undefined_instruction_get_encoding;
+ instr->get_keyword = g_undefined_instruction_get_keyword;
}
@@ -144,16 +117,22 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass)
* *
******************************************************************************/
-static void g_undef_instruction_init(GUndefInstruction *instr)
+static void g_undefined_instruction_init(GUndefinedInstruction *instr)
{
- GET_UNDEF_INSTR_EXTRA(instr)->behavior = IEB_UNDEFINED;
+ undef_extra_data_t extra; /* Données insérées à consulter*/
+
+ extra = GET_UNDEF_INSTR_EXTRA(instr);
+
+ extra.behavior = IEB_UNDEFINED;
+
+ SET_UNDEF_INSTR_EXTRA(instr, &extra);
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -163,16 +142,16 @@ static void g_undef_instruction_init(GUndefInstruction *instr)
* *
******************************************************************************/
-static void g_undef_instruction_dispose(GUndefInstruction *instr)
+static void g_undefined_instruction_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_undef_instruction_parent_class)->dispose(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_undefined_instruction_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : instr = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -182,9 +161,9 @@ static void g_undef_instruction_dispose(GUndefInstruction *instr)
* *
******************************************************************************/
-static void g_undef_instruction_finalize(GUndefInstruction *instr)
+static void g_undefined_instruction_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_undef_instruction_parent_class)->finalize(G_OBJECT(instr));
+ G_OBJECT_CLASS(g_undefined_instruction_parent_class)->finalize(object);
}
@@ -201,16 +180,14 @@ static void g_undef_instruction_finalize(GUndefInstruction *instr)
* *
******************************************************************************/
-GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior)
+GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior behavior)
{
GArchInstruction *result; /* Instruction à retourner */
- undef_extra_data_t *extra; /* Données insérées à modifier */
- result = g_object_new(G_TYPE_UNDEF_INSTRUCTION, NULL);
+ result = g_object_new(G_TYPE_UNDEFINED_INSTRUCTION, NULL);
- extra = GET_UNDEF_INSTR_EXTRA(result);
-
- extra->behavior = behavior;
+ if (!g_undefined_instruction_create(G_UNDEFINED_INSTRUCTION(result), behavior))
+ g_clear_object(&result);
return result;
@@ -219,90 +196,10 @@ GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior)
/******************************************************************************
* *
-* Paramètres : instr = instruction quelconque à consulter. *
-* *
-* Description : Indique l'encodage d'une instruction de façon détaillée. *
-* *
-* Retour : Description humaine de l'encodage utilisé. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const char *g_undef_instruction_get_encoding(const GUndefInstruction *instr)
-{
- const char *result; /* Description à retourner */
-
- result = _("Undefined");
-
- return result;
-
-}
-
-
-/******************************************************************************
+* Paramètres : instr = instance à initialiser pleinement. *
+* behavior = état réel du CPU après une passe de l'instruction.*
* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* *
-* Description : Fournit le nom humain de l'instruction manipulée. *
-* *
-* Retour : Mot clef de bas niveau. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr)
-{
- const char *result; /* Désignation à retourner */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- switch (extra->behavior)
- {
- case IEB_NOP:
- result = "nop";
- break;
-
- case IEB_UNDEFINED:
- result = "undefined";
- break;
-
- case IEB_UNPREDICTABLE:
- result = "unpredictable";
- break;
-
- case IEB_RESERVED:
- result = "reserved";
- break;
-
- default:
- assert(false);
- result = NULL;
- break;
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Charge une instruction depuis une mémoire tampon. *
+* Description : Met en place une instruction au comportement indéfini. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -310,122 +207,24 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr)
* *
******************************************************************************/
-static bool g_undef_instruction_unserialize(GUndefInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+bool g_undefined_instruction_create(GUndefinedInstruction *instr, InstrExpectedBehavior behavior)
{
bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
- uint8_t val; /* Champ de bits manipulé */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
+ undef_extra_data_t extra; /* Données insérées à modifier */
- result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf);
+ result = true;
- if (result)
- {
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
- extra->behavior = val;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde une instruction dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_undef_instruction_serialize(GUndefInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
-
- result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf);
-
- if (result)
- {
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false);
+ extra = GET_UNDEF_INSTR_EXTRA(instr);
- UNLOCK_GOBJECT_EXTRA(extra);
+ extra.behavior = behavior;
- }
+ SET_UNDEF_INSTR_EXTRA(instr, &extra);
return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* OFFRE DE CAPACITES DE GENERATION */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction d'assemblage à représenter. *
-* line = ligne de rendu à compléter. *
-* index = indice de cette même ligne dans le tampon global. *
-* repeat = indice d'utilisations successives du générateur. *
-* content = éventuel contenu binaire brut à imprimer. *
-* *
-* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content)
-{
- GArchInstruction *base; /* Version de base */
- const char *key; /* Mot clef principal */
- size_t klen; /* Taille de ce mot clef */
-
- base = G_ARCH_INSTRUCTION(instr);
-
- g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range));
-
- g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, VMPA_NO_PHYSICAL);
-
- /* Instruction proprement dite */
-
- key = g_arch_instruction_get_keyword(base);
- klen = strlen(key);
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL);
-
-}
-
-
/******************************************************************************
* *
* Paramètres : instr = instruction à consulter. *
@@ -438,18 +237,14 @@ static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *lin
* *
******************************************************************************/
-InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *instr)
+InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *instr)
{
InstrExpectedBehavior result; /* Comportement à retourner */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
+ undef_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_UNDEF_INSTR_EXTRA(instr);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->behavior;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.behavior;
return result;
@@ -464,41 +259,21 @@ InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : instr = instruction quelconque à consulter. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+static char *g_undefined_instruction_get_encoding(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
- uint8_t val; /* Champ de bits manipulé */
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
-
- result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
-
- if (result)
- {
- extra = GET_UNDEF_INSTR_EXTRA(instr);
-
- LOCK_GOBJECT_EXTRA(extra);
+ char *result; /* Description à retourner */
- result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
- extra->behavior = val;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- }
+ result = strdup(_("Undefined"));
return result;
@@ -507,37 +282,45 @@ static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *s
/******************************************************************************
* *
-* Paramètres : instr = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : instr = instruction d'assemblage à consulter. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Fournit le nom humain de l'instruction manipulée. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_undef_instruction_store(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+static char *g_undefined_instruction_get_keyword(const GArchInstruction *instr)
{
- bool result; /* Bilan à retourner */
- GArchInstructionClass *parent; /* Classe parente à consulter */
- undef_extra_data_t *extra; /* Données insérées à consulter*/
-
- parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
+ char *result; /* Désignation à retourner */
+ undef_extra_data_t extra; /* Données insérées à consulter*/
- result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+ extra = GET_UNDEF_INSTR_EXTRA(instr);
- if (result)
+ switch (extra.behavior)
{
- extra = GET_UNDEF_INSTR_EXTRA(instr);
+ case IEB_NOP:
+ result = strdup("nop");
+ break;
- LOCK_GOBJECT_EXTRA(extra);
+ case IEB_UNDEFINED:
+ result = strdup("undefined");
+ break;
- result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false);
+ case IEB_UNPREDICTABLE:
+ result = strdup("unpredictable");
+ break;
- UNLOCK_GOBJECT_EXTRA(extra);
+ case IEB_RESERVED:
+ result = strdup("reserved");
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
}
diff --git a/src/arch/instructions/undefined.h b/src/arch/instructions/undefined.h
index 8f35f35..d4b35f4 100644
--- a/src/arch/instructions/undefined.h
+++ b/src/arch/instructions/undefined.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* undefined.h - prototypes pour les instructions au comportement non défini
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,27 +25,14 @@
#define _ARCH_INSTRUCTIONS_UNDEFINED_H
-#include <glib-object.h>
-
-
#include "../instruction.h"
-#include "../vmpa.h"
-
+#include "../../glibext/helpers.h"
-#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type()
-#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstruction))
-#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UNDEF_INSTRUCTION))
-#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass))
-#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION))
-#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass))
+#define G_TYPE_UNDEFINED_INSTRUCTION (g_undefined_instruction_get_type())
-/* Définition générique d'une instruction au comportement non défini (instance) */
-typedef struct _GUndefInstruction GUndefInstruction;
-
-/* Définition générique d'une instruction au comportement non défini (classe) */
-typedef struct _GUndefInstructionClass GUndefInstructionClass;
+DECLARE_GTYPE(GUndefinedInstruction, g_undefined_instruction, G, UNDEFINED_INSTRUCTION);
/* Etat précis de l'instruction */
@@ -59,14 +46,11 @@ typedef enum _InstrExpectedBehavior
} InstrExpectedBehavior;
-/* Indique le type défini pour une instruction au comportement non défini. */
-GType g_undef_instruction_get_type(void);
-
/* Crée une instruction au comportement nominalement indéfini. */
-GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior);
+GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior);
/* Indique le type de conséquences réél de l'instruction. */
-InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *);
+InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *);
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index e6c1232..10c079b 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* operand-int.h - prototypes pour la définition générique interne des opérandes
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,13 +26,23 @@
#include "operand.h"
+#include "../common/szbin.h"
+#include "../glibext/objhole-int.h"
+
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+//typedef bool (* arch_operand_to_string_fc) (const GArchOperand *operand, unsigned int flags, sized_binary_t *);
+
+
+
+#if 0
#include <stdbool.h>
#include "../analysis/storage/storage.h"
-#include "../glibext/objhole.h"
@@ -71,46 +81,29 @@ typedef bool (* load_operand_fc) (GArchOperand *, GObjectStorage *, packed_buffe
typedef bool (* store_operand_fc) (GArchOperand *, GObjectStorage *, packed_buffer_t *);
-/* Informations glissées dans la structure GObject de GArchOperand */
-typedef struct _operand_extra_data_t
-{
- ArchOperandFlag flags; /* Informations diverses */
-} operand_extra_data_t;
-/* Encapsulation avec un verrou d'accès */
-typedef union _operand_obj_extra_t
-{
- operand_extra_data_t data; /* Données embarquées */
- lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */
+#endif
-} operand_obj_extra_t;
/* Définition générique d'un opérande d'architecture (instance) */
struct _GArchOperand
{
- GObject parent; /* A laisser en premier */
-
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
-
- /**
- * L'inclusion des informations suivantes dépend de l'architecture.
- *
- * Si la structure GObject possède un trou, on remplit de préférence
- * ce dernier.
- */
-
- operand_obj_extra_t extra; /* Externalisation embarquée */
-
-#endif
+ GThickObject parent; /* A laisser en premier */
};
/* Définition générique d'un opérande d'architecture (classe) */
struct _GArchOperandClass
{
- GObjectClass parent; /* A laisser en premier */
+ GThickObjectClass parent; /* A laisser en premier */
+
+
+
+
+
+#if 0
operand_compare_fc compare; /* Comparaison d'opérandes */
find_inner_operand_fc find_inner; /* Définition d'un chemin */
@@ -128,29 +121,57 @@ struct _GArchOperandClass
load_operand_fc load; /* Chargement depuis un tampon */
store_operand_fc store; /* Conservation dans un tampon */
+#endif
+
};
+
/**
* Accès aux informations éventuellement déportées.
*/
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
-# define GET_ARCH_OP_EXTRA(op) (operand_extra_data_t *)&op->extra
+#define ARCH_OPERAND_EXTRA_DATA(mx) \
+ \
+ unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \
+ \
+ /** \
+ * ArchOperandFlag \
+ */ \
+ unsigned int flags : mx;
-#else
-# define GET_ARCH_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), operand_extra_data_t)
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _operand_extra_data_t
+{
+ ARCH_OPERAND_EXTRA_DATA(3); /* Informations pour l'opérande*/
+
+} operand_extra_data_t;
+
+
+#define GET_ARCH_OP_EXTRA(op) \
+ GET_GOBJECT_EXTRA(op, operand_extra_data_t)
+
+#define SET_ARCH_OP_EXTRA(op, data) \
+ SET_GOBJECT_EXTRA(op, operand_extra_data_t, data)
+
+
+
+
+
+
+
+
+#if 0
-#endif
/* Ajoute une information complémentaire à un opérande. */
-bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool);
+//bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool);
/* Retire une information complémentaire à un opérande. */
-bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool);
+//bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool);
@@ -190,5 +211,7 @@ bool g_arch_operand_store_generic_fixed(GArchOperand *, GObjectStorage *, packed
bool g_arch_operand_store_generic_variadic(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+#endif
+
#endif /* _ARCH_OPERAND_INT_H */
diff --git a/src/arch/operand-ui-int.h b/src/arch/operand-ui-int.h
new file mode 100644
index 0000000..c1173f3
--- /dev/null
+++ b/src/arch/operand-ui-int.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand-ui-int.h - prototypes pour la définition générique interne des opérandes sous forme graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERAND_UI_INT_H
+#define _ARCH_OPERAND_UI_INT_H
+
+
+#include "operand-ui.h"
+
+
+
+/* Traduit un opérande en version humainement lisible. */
+typedef void (* print_operand_ui_fc) (const GArchOperandUI *, GBufferLine *);
+
+/* Construit un petit résumé concis de l'opérande. */
+typedef char * (* build_operand_ui_tooltip_fc) (const GArchOperandUI *, const GLoadedBinary *);
+
+
+
+/* Définition générique d'un opérande d'architecture (interface) */
+struct _GArchOperandUIInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ print_operand_ui_fc print; /* Texte humain équivalent */
+ build_operand_ui_tooltip_fc build_tooltip; /* Définition de description*/
+
+};
+
+
+
+#endif /* _ARCH_OPERAND_UI_INT_H */
diff --git a/src/arch/operand-ui.c b/src/arch/operand-ui.c
new file mode 100644
index 0000000..ff7ad1b
--- /dev/null
+++ b/src/arch/operand-ui.c
@@ -0,0 +1,111 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand-ui.c - gestion générique des opérandes sous forme graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "operand-ui.h"
+
+
+#include "operand-ui-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface d'opérande UI. */
+static void g_arch_operand_ui_default_init(GArchOperandUIInterface *);
+
+
+
+/* Indique le type défini pour un opérande d'architecture avec représentation graphique. */
+G_DEFINE_INTERFACE(GArchOperandUI, g_arch_operand_ui, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'opérande UI. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_operand_ui_default_init(GArchOperandUIInterface *iface)
+{
+ iface->print = NULL;
+ iface->build_tooltip = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_arch_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line)
+{
+ GArchOperandUIInterface *iface; /* Interface utilisée */
+
+ iface = G_ARCH_OPERAND_UI_GET_IFACE(operand);
+
+ iface->print(operand, line);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* binary = informations relatives au binaire chargé. *
+* *
+* Description : Construit un petit résumé concis de l'opérande. *
+* *
+* Retour : Chaîne de caractères à libérer après usage ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_arch_operand_ui_build_tooltip(const GArchOperandUI *operand, const GLoadedBinary *binary)
+{
+ char *result; /* Description à retourner */
+ GArchOperandUIInterface *iface; /* Interface utilisée */
+
+ iface = G_ARCH_OPERAND_UI_GET_IFACE(operand);
+
+ if (iface->build_tooltip != NULL)
+ result = iface->build_tooltip(operand, binary);
+ else
+ result = NULL;
+
+ return result;
+
+}
diff --git a/src/arch/operand-ui.h b/src/arch/operand-ui.h
new file mode 100644
index 0000000..b197645
--- /dev/null
+++ b/src/arch/operand-ui.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand-ui.h - prototypes pour la gestion générique des opérandes sous forme graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERAND_UI_H
+#define _ARCH_OPERAND_UI_H
+
+
+#include "../glibext/bufferline.h"
+#include "../glibext/helpers.h"
+
+
+
+#define G_TYPE_ARCH_OPERAND_UI (g_arch_operand_ui_get_type())
+
+DECLARE_INTERFACE(GArchOperandUI, g_arch_operand_ui, G, ARCH_OPERAND_UI);
+
+
+
+// TODO : REMME
+//typedef void *GBufferLine;
+typedef void *GLoadedBinary;
+/////
+
+
+
+/* Traduit un opérande en version humainement lisible. */
+void g_arch_operand_ui_print(const GArchOperandUI *, GBufferLine *);
+
+/* Construit un petit résumé concis de l'opérande. */
+char *g_arch_operand_ui_build_tooltip(const GArchOperandUI *, const GLoadedBinary *);
+
+
+
+#endif /* _ARCH_OPERAND_UI_H */
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 0f5ffd5..d3e837c 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* operand.c - gestion générique des opérandes
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,17 +25,16 @@
#include <assert.h>
-#include <malloc.h>
-#include <string.h>
#include "operand-int.h"
-#include "storage.h"
-#include "../analysis/storage/serialize-int.h"
#include "../common/fnv1a.h"
#include "../common/sort.h"
-#include "../core/logs.h"
+#include "../glibext/comparable-int.h"
+#include "../glibext/hashable-int.h"
+#include "../glibext/serialize-int.h"
#include "../glibext/singleton-int.h"
+#include "../glibext/strbuilder-int.h"
@@ -45,66 +44,67 @@
/* Initialise la classe générique des opérandes. */
static void g_arch_operand_class_init(GArchOperandClass *);
-/* Initialise une instance d'opérande d'architecture. */
-static void g_arch_operand_init(GArchOperand *);
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_arch_operand_comparable_object_iface_init(GComparableObjectInterface *);
-/* Procède à l'initialisation de l'interface de singleton. */
-static void g_arch_operand_singleton_init(GSingletonCandidateInterface *);
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_arch_operand_hashable_object_iface_init(GHashableObjectInterface *);
/* Procède à l'initialisation de l'interface de sérialisation. */
-static void g_arch_operand_serializable_init(GSerializableObjectInterface *);
+static void g_arch_operand_serializable_object_iface_init(GSerializableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface de rassemblement. */
+static void g_arch_operand_singleton_candidate_iface_init(GSingletonCandidateInterface *);
+
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_arch_operand_string_builder_iface_init(GStringBuilderInterface *);
+
+/* Initialise une instance d'opérande d'architecture. */
+static void g_arch_operand_init(GArchOperand *);
/* Supprime toutes les références externes. */
-static void g_arch_operand_dispose(GArchOperand *);
+static void g_arch_operand_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_arch_operand_finalize(GArchOperand *);
+static void g_arch_operand_finalize(GObject *);
-/* Compare un opérande avec un autre. */
-static int _g_arch_operand_compare(const GArchOperand *, const GArchOperand *, bool);
+/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */
-/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */
+/* Réalise une comparaison étendue entre objets. */
+static int g_arch_operand_compare(const GComparableObject *, const GComparableObject *);
-/* Fournit une liste de candidats embarqués par un candidat. */
-GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *);
-/* Met à jour une liste de candidats embarqués par un candidat. */
-void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint _g_arch_operand_hash(const GArchOperand *, bool);
+/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint g_arch_operand_hash(const GArchOperand *);
-/* Détermine si deux candidats à l'unicité sont identiques. */
-static gboolean g_arch_operand_is_equal(const GArchOperand *, const GArchOperand *);
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+static guint g_arch_operand_hash(const GHashableObject *);
-/* Marque un candidat comme figé. */
-static void g_arch_operand_set_read_only(GArchOperand *);
-/* Indique si le candidat est figé. */
-static bool g_arch_operand_is_read_only(GArchOperand *);
+/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
-/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+/* Charge un objet depuis un flux de données. */
+static bool g_arch_operand_load(GSerializableObject *, GObjectStorage *, int);
+/* Sauvegarde un objet dans un flux de données. */
+static bool g_arch_operand_store(const GSerializableObject *, GObjectStorage *, int);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool _g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool _g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+
+/* Marque un candidat comme figé. */
+static void g_arch_operand_mark_as_read_only(GSingletonCandidate *);
+
+/* Indique si le candidat est figé. */
+static bool g_arch_operand_is_read_only(const GSingletonCandidate *);
@@ -114,9 +114,12 @@ static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer
/* Indique le type défini pour un opérande d'architecture. */
-G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_init)
- G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_init));
+G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_THICK_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_arch_operand_comparable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_arch_operand_hashable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_candidate_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_arch_operand_string_builder_iface_init));
/******************************************************************************
@@ -134,30 +137,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT,
static void g_arch_operand_class_init(GArchOperandClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchOperandClass *operand; /* Encore une autre vision... */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_operand_dispose;
- object->finalize = (GObjectFinalizeFunc)g_arch_operand_finalize;
-
- operand = G_ARCH_OPERAND_CLASS(klass);
-
- operand->compare = (operand_compare_fc)_g_arch_operand_compare;
-
- operand->hash = _g_arch_operand_hash;
-
- operand->load = (load_operand_fc)_g_arch_operand_load;
- operand->store = (store_operand_fc)_g_arch_operand_store;
+ object->dispose = g_arch_operand_dispose;
+ object->finalize = g_arch_operand_finalize;
}
/******************************************************************************
* *
-* Paramètres : operand = instance à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Initialise une instance d'opérande d'architecture. *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
* *
* Retour : - *
* *
@@ -165,13 +158,9 @@ static void g_arch_operand_class_init(GArchOperandClass *klass)
* *
******************************************************************************/
-static void g_arch_operand_init(GArchOperand *operand)
+static void g_arch_operand_comparable_object_iface_init(GComparableObjectInterface *iface)
{
- operand_extra_data_t *extra; /* Données insérées à modifier */
-
- extra = GET_ARCH_OP_EXTRA(operand);
-
- INIT_GOBJECT_EXTRA_LOCK(extra);
+ iface->compare = g_arch_operand_compare;
}
@@ -180,7 +169,7 @@ static void g_arch_operand_init(GArchOperand *operand)
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Procède à l'initialisation de l'interface de singleton. *
+* Description : Procède à l'initialisation de l'interface de détermination. *
* *
* Retour : - *
* *
@@ -188,16 +177,9 @@ static void g_arch_operand_init(GArchOperand *operand)
* *
******************************************************************************/
-static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface)
+static void g_arch_operand_hashable_object_iface_init(GHashableObjectInterface *iface)
{
- iface->list_inner = (list_inner_instances_fc)g_arch_operand_list_inner_instances;
- iface->update_inner = (update_inner_instances_fc)g_arch_operand_update_inner_instances;
-
- iface->hash = (hash_candidate_fc)g_arch_operand_hash;
- iface->is_equal = (is_candidate_equal_fc)g_arch_operand_is_equal;
-
- iface->set_ro = (set_candidate_ro_fc)g_arch_operand_set_read_only;
- iface->is_ro = (is_candidate_ro_fc)g_arch_operand_is_read_only;
+ iface->hash = g_arch_operand_hash;
}
@@ -214,38 +196,19 @@ static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface)
* *
******************************************************************************/
-static void g_arch_operand_serializable_init(GSerializableObjectInterface *iface)
+static void g_arch_operand_serializable_object_iface_init(GSerializableObjectInterface *iface)
{
- iface->load = (load_serializable_object_cb)g_arch_operand_load;
- iface->store = (store_serializable_object_cb)g_arch_operand_store;
+ iface->load = g_arch_operand_load;
+ iface->store = g_arch_operand_store;
}
/******************************************************************************
* *
-* Paramètres : operand = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_arch_operand_dispose(GArchOperand *operand)
-{
- G_OBJECT_CLASS(g_arch_operand_parent_class)->dispose(G_OBJECT(operand));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = instance d'objet GLib à traiter. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Procède à la libération totale de la mémoire. *
+* Description : Procède à l'initialisation de l'interface de rassemblement. *
* *
* Retour : - *
* *
@@ -253,147 +216,59 @@ static void g_arch_operand_dispose(GArchOperand *operand)
* *
******************************************************************************/
-static void g_arch_operand_finalize(GArchOperand *operand)
+static void g_arch_operand_singleton_candidate_iface_init(GSingletonCandidateInterface *iface)
{
- G_OBJECT_CLASS(g_arch_operand_parent_class)->finalize(G_OBJECT(operand));
-
-}
-
-
-/******************************************************************************
-* *
-* 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. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int _g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b, bool lock)
-{
- int result; /* Bilan à faire remonter */
- operand_extra_data_t *ea; /* Données insérées à consulter*/
- operand_extra_data_t *eb; /* Données insérées à consulter*/
-
- assert(!lock);
-
- ea = GET_ARCH_OP_EXTRA(a);
- eb = GET_ARCH_OP_EXTRA(b);
+ iface->list_inner = NULL;
+ iface->update_inner = NULL;
- result = sort_unsigned_long(ea->flags, eb->flags);
-
- return result;
+ iface->mark_as_ro = g_arch_operand_mark_as_read_only;
+ iface->is_ro = g_arch_operand_is_read_only;
}
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
-* *
-* Description : Compare un opérande avec un autre. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-int g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b)
-{
- int result; /* Bilan à faire remonter */
- GType type_a; /* Type de l'object A */
- GType type_b; /* Type de l'object B */
-
- type_a = G_OBJECT_TYPE(G_OBJECT(a));
- type_b = G_OBJECT_TYPE(G_OBJECT(b));
-
- assert(sizeof(GType) <= sizeof(unsigned long));
-
- result = sort_unsigned_long(type_a, type_b);
-
- if (result == 0)
- result = G_ARCH_OPERAND_GET_CLASS(a)->compare(a, b, true);
-
- return result;
-
-}
-
-
-/******************************************************************************
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Paramètres : operand = opérande à consulter. *
-* target = instruction à venir retrouver. *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
* *
-* Description : Détermine le chemin conduisant à un opérande interne. *
-* *
-* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target)
+static void g_arch_operand_string_builder_iface_init(GStringBuilderInterface *iface)
{
- char *result; /* Chemin à retourner */
- GArchOperandClass *class; /* Classe associée à l'objet */
-
- class = G_ARCH_OPERAND_GET_CLASS(operand);
-
- if (class->find_inner != NULL)
- result = class->find_inner(operand, target);
-
- else
- result = NULL;
-
- return result;
+ iface->to_string = NULL;
}
/******************************************************************************
* *
-* Paramètres : operand = opérande à consulter. *
-* path = chemin d'accès à un opérande à retrouver. *
+* Paramètres : operand = instance à initialiser. *
* *
-* Description : Obtient l'opérande correspondant à un chemin donné. *
+* Description : Initialise une instance d'opérande d'architecture. *
* *
-* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path)
+static void g_arch_operand_init(GArchOperand *operand)
{
- GArchOperand *result; /* Opérande trouvée à renvoyer */
- GArchOperandClass *class; /* Classe associée à l'objet */
-
- class = G_ARCH_OPERAND_GET_CLASS(operand);
-
- if (class->get_inner != NULL)
- result = class->get_inner(operand, path);
-
- else
- result = NULL;
-
- return result;
}
/******************************************************************************
* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
-* Description : Traduit un opérande en version humainement lisible. *
+* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
@@ -401,54 +276,36 @@ GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *ope
* *
******************************************************************************/
-void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line)
+static void g_arch_operand_dispose(GObject *object)
{
- G_ARCH_OPERAND_GET_CLASS(operand)->print(operand, line);
+ G_OBJECT_CLASS(g_arch_operand_parent_class)->dispose(object);
}
-#ifdef INCLUDE_GTK_SUPPORT
-
-
/******************************************************************************
* *
-* Paramètres : operand = opérande à consulter. *
-* binary = informations relatives au binaire chargé. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
-* Description : Construit un petit résumé concis de l'opérande. *
+* Description : Procède à la libération totale de la mémoire. *
* *
-* Retour : Chaîne de caractères à libérer après usage ou NULL. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBinary *binary)
+static void g_arch_operand_finalize(GObject *object)
{
- char *result; /* Description à retourner */
- GArchOperandClass *class; /* Classe associée à l'objet */
-
- class = G_ARCH_OPERAND_GET_CLASS(operand);
-
- if (class->build_tooltip != NULL)
- result = class->build_tooltip(operand, binary);
- else
- result = NULL;
-
- return result;
+ G_OBJECT_CLASS(g_arch_operand_parent_class)->finalize(object);
}
-#endif
-
-
/******************************************************************************
* *
* Paramètres : operand = opérande à venir modifier. *
* flag = drapeau d'information complémentaire à planter. *
-* lock = indique un besoin de verrouillage des données. *
* *
* Description : Ajoute une information complémentaire à un opérande. *
* *
@@ -458,48 +315,20 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin
* *
******************************************************************************/
-bool _g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock)
+bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag)
{
bool result; /* Bilan à retourner */
- operand_extra_data_t *extra; /* Données insérées à modifier */
+ operand_extra_data_t extra; /* Données insérées à modifier */
assert(flag <= AOF_HIGH_USER);
extra = GET_ARCH_OP_EXTRA(operand);
- if (lock)
- LOCK_GOBJECT_EXTRA(extra);
-
- result = !(extra->flags & flag);
-
- extra->flags |= flag;
-
- if (lock)
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à venir modifier. *
-* flag = drapeau d'information complémentaire à planter. *
-* *
-* Description : Ajoute une information complémentaire à un opérande. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result = !(extra.flags & flag);
-bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag)
-{
- bool result; /* Bilan à retourner */
+ extra.flags |= flag;
- result = _g_arch_operand_set_flag(operand, flag, true);
+ SET_ARCH_OP_EXTRA(operand, &extra);
return result;
@@ -510,7 +339,6 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag)
* *
* Paramètres : operand = opérande à venir modifier. *
* flag = drapeau d'information complémentaire à planter. *
-* lock = indique un besoin de verrouillage des données. *
* *
* Description : Retire une information complémentaire à un opérande. *
* *
@@ -520,46 +348,20 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag)
* *
******************************************************************************/
-bool _g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock)
+bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag)
{
bool result; /* Bilan à retourner */
- operand_extra_data_t *extra; /* Données insérées à modifier */
+ operand_extra_data_t extra; /* Données insérées à modifier */
assert(flag <= AOF_HIGH_USER);
extra = GET_ARCH_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = (extra->flags & flag);
-
- extra->flags &= ~flag;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à venir modifier. *
-* flag = drapeau d'information complémentaire à planter. *
-* *
-* Description : Retire une information complémentaire à un opérande. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result = (extra.flags & flag);
-bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag)
-{
- bool result; /* Bilan à retourner */
+ extra.flags &= ~flag;
- result = _g_arch_operand_unset_flag(operand, flag, true);
+ SET_ARCH_OP_EXTRA(operand, &extra);
return result;
@@ -582,17 +384,13 @@ bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag)
bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag)
{
bool result; /* Bilan à retourner */
- operand_extra_data_t *extra; /* Données insérées à modifier */
+ operand_extra_data_t extra; /* Données insérées à modifier */
assert(flag <= AOF_HIGH_USER);
extra = GET_ARCH_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = (extra->flags & flag);
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = (extra.flags & flag);
return result;
@@ -614,15 +412,11 @@ bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag)
ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand)
{
ArchOperandFlag result; /* Fanions à retourner */
- operand_extra_data_t *extra; /* Données insérées à modifier */
+ operand_extra_data_t extra; /* Données insérées à modifier */
extra = GET_ARCH_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->flags;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.flags;
return result;
@@ -630,39 +424,40 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand)
-/* ---------------------------------------------------------------------------------- */
-/* CONTROLE DU VOLUME DES INSTANCES */
-/* ---------------------------------------------------------------------------------- */
+
+
+
+
+#if 0
+
+
/******************************************************************************
* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* count = quantité d'instances à l'unicité internes. *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
* *
-* Description : Fournit une liste de candidats embarqués par un candidat. *
+* Description : Détermine le chemin conduisant à un opérande interne. *
* *
-* Retour : Liste de candidats internes ou NULL si aucun. *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, size_t *count)
+char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target)
{
- GArchOperand **result; /* Instances à retourner */
+ char *result; /* Chemin à retourner */
GArchOperandClass *class; /* Classe associée à l'objet */
class = G_ARCH_OPERAND_GET_CLASS(operand);
- if (class->list_inner == NULL)
- {
- *count = 0;
- result = NULL;
- }
+ if (class->find_inner != NULL)
+ result = class->find_inner(operand, target);
else
- result = class->list_inner(operand, count);
+ result = NULL;
return result;
@@ -671,105 +466,59 @@ GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand,
/******************************************************************************
* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* instances = liste de candidats internes devenus singletons. *
-* count = quantité d'instances à l'unicité internes. *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
* *
-* Description : Met à jour une liste de candidats embarqués par un candidat. *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
* *
-* Retour : - *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_arch_operand_update_inner_instances(GArchOperand *operand, GArchOperand **instances, size_t count)
+GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path)
{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
GArchOperandClass *class; /* Classe associée à l'objet */
class = G_ARCH_OPERAND_GET_CLASS(operand);
- if (class->update_inner == NULL)
- assert(class->list_inner == NULL);
+ if (class->get_inner != NULL)
+ result = class->get_inner(operand, path);
else
- {
- assert(class->list_inner != NULL);
- class->update_inner(operand, instances, count);
- }
+ result = NULL;
+
+ return result;
}
-/******************************************************************************
-* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* lock = précise le besoin en verrouillage. *
-* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
-* *
-* Retour : Empreinte de l'élément représenté. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+#endif
-static guint _g_arch_operand_hash(const GArchOperand *operand, bool lock)
-{
- guint result; /* Valeur à retourner */
- const char *name; /* Désignation du type d'object*/
- fnv64_t name_hash; /* Empreinte du nom */
- operand_extra_data_t *extra; /* Données insérées à modifier */
- assert(!lock);
- name = G_OBJECT_TYPE_NAME(G_OBJECT(operand));
- name_hash = fnv_64a_hash(name);
- result = (name_hash & 0xffffffff);
- result ^= (name_hash >> 32);
- extra = GET_ARCH_OP_EXTRA(operand);
- result ^= extra->flags;
- return result;
-}
-/******************************************************************************
-* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
-* *
-* Retour : Empreinte de l'élément représenté. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-static guint g_arch_operand_hash(const GArchOperand *operand)
-{
- guint result; /* Valeur à retourner */
- GArchOperandClass *class; /* Classe associée à l'objet */
-
- class = G_ARCH_OPERAND_GET_CLASS(operand);
-
- result = class->hash(operand, true);
- return result;
-
-}
+/* ---------------------------------------------------------------------------------- */
+/* COMPARAISON DETAILLEE DE DEUX OBJETS */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
+* Description : Réalise une comparaison étendue entre objets. *
* *
* Retour : Bilan de la comparaison. *
* *
@@ -777,56 +526,56 @@ static guint g_arch_operand_hash(const GArchOperand *operand)
* *
******************************************************************************/
-static gboolean g_arch_operand_is_equal(const GArchOperand *operand, const GArchOperand *other)
+static int g_arch_operand_compare(const GComparableObject *object, const GComparableObject *other)
{
- gboolean result; /* Bilan à renvoyer */
- int ret; /* Bilan d'une comparaison */
+ int result; /* Bilan à retourner */
+ operand_extra_data_t extra_op; /* Données insérées à consulter*/
+ operand_extra_data_t extra_other; /* Données insérées à consulter*/
- ret = g_arch_operand_compare(operand, other);
+ extra_op = GET_ARCH_OP_EXTRA(object);
+ extra_other = GET_ARCH_OP_EXTRA(other);
- result = (ret == 0);
+ result = sort_unsigned_long(extra_op.flags, extra_other.flags);
return result;
}
-/******************************************************************************
-* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* *
-* Description : Marque un candidat comme figé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_arch_operand_set_read_only(GArchOperand *operand)
-{
- g_arch_operand_set_flag(operand, AOF_READ_ONLY);
-}
+/* ---------------------------------------------------------------------------------- */
+/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
+* Paramètres : object = objet dont l'instance est à consulter. *
* *
-* Description : Indique si le candidat est figé. *
+* Description : Calcule l'empreinte sur 32 bits d'un objet. *
* *
-* Retour : true si le contenu du candidat ne peut plus être modifié. *
+* Retour : Valeur de représentation, unique pour l'objet ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_arch_operand_is_read_only(GArchOperand *operand)
+static guint g_arch_operand_hash(const GHashableObject *object)
{
- bool result; /* Etat à retourner */
+ guint result; /* Valeur à retourner */
+ const char *name; /* Désignation du type d'object*/
+ fnv64_t name_hash; /* Empreinte du nom */
+ operand_extra_data_t extra; /* Données insérées à consulter*/
- result = g_arch_operand_has_flag(operand, AOF_READ_ONLY);
+ name = G_OBJECT_TYPE_NAME(G_OBJECT(object));
+ name_hash = fnv_64a_hash(name);
+
+ result = (name_hash & 0xffffffff);
+ result ^= (name_hash >> 32);
+
+ extra = GET_ARCH_OP_EXTRA(object);
+
+ result ^= extra.flags;
return result;
@@ -835,17 +584,17 @@ static bool g_arch_operand_is_read_only(GArchOperand *operand)
/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION ET RECHARGEMENT DES DONNEES */
+/* MECANISMES DE CONSERVATION ET RESTAURATION */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Charge un objet depuis un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -853,22 +602,15 @@ static bool g_arch_operand_is_read_only(GArchOperand *operand)
* *
******************************************************************************/
-static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_arch_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- operand_extra_data_t *extra; /* Données insérées à consulter*/
- uleb128_t value; /* Valeur ULEB128 à charger */
-
- extra = GET_ARCH_OP_EXTRA(operand);
+ uleb128_t extra; /* Données embarquées */
- LOCK_GOBJECT_EXTRA(extra);
-
- result = unpack_uleb128(&value, pbuf);
+ result = load_uleb128(&extra, fd);
if (result)
- extra->flags = value;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ g_thick_object_set_extra(G_THICK_OBJECT(object), extra);
return result;
@@ -877,11 +619,11 @@ static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage,
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Sauvegarde un objet dans un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -889,74 +631,69 @@ static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage,
* *
******************************************************************************/
-static bool g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_arch_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- GArchOperandClass *class; /* Classe à activer */
+ guint extra; /* Données embarquées */
- class = G_ARCH_OPERAND_GET_CLASS(operand);
+ extra = g_thick_object_get_extra(G_THICK_OBJECT(object));
- result = class->load(operand, storage, pbuf);
+ result = store_uleb128((uleb128_t []) { extra }, fd);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* CONTROLE DU VOLUME DES INSTANCES */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : candidate = objet dont l'instance se veut unique. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Marque un candidat comme figé. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool _g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static void g_arch_operand_mark_as_read_only(GSingletonCandidate *candidate)
{
- bool result; /* Bilan à retourner */
- operand_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_ARCH_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf);
+ GArchOperand *operand; /* Version spécialisée */
- UNLOCK_GOBJECT_EXTRA(extra);
+ operand = G_ARCH_OPERAND(candidate);
- return result;
+ g_arch_operand_set_flag(operand, AOF_READ_ONLY);
}
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Indique si le candidat est figé. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : true si le contenu du candidat ne peut plus être modifié. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_arch_operand_is_read_only(const GSingletonCandidate *candidate)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *class; /* Classe à activer */
+ bool result; /* Etat à retourner */
+ GArchOperand *operand; /* Version spécialisée */
- class = G_ARCH_OPERAND_GET_CLASS(operand);
+ operand = G_ARCH_OPERAND(candidate);
- result = class->store(operand, storage, pbuf);
+ result = g_arch_operand_has_flag(operand, AOF_READ_ONLY);
return result;
diff --git a/src/arch/operand.h b/src/arch/operand.h
index 234ee64..72a1b56 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* operand.h - prototypes pour la gestion générique des opérandes
*
- * Copyright (C) 2008-2020 Cyrille Bagard
+ * Copyright (C) 2008-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,20 +25,16 @@
#define _ARCH_OPERAND_H
-#include <glib-object.h>
-
+#include <stdbool.h>
-#include "../common/packed.h"
-#include "../format/format.h"
-#include "../glibext/bufferline.h"
+#include "../glibext/helpers.h"
-/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */
+#define G_TYPE_ARCH_OPERAND (g_arch_operand_get_type())
-/* Depuis "../analysis/binary.h" : description de fichier binaire */
-typedef struct _GLoadedBinary GLoadedBinary;
+DECLARE_GTYPE(GArchOperand, g_arch_operand, G, ARCH_OPERAND);
/* Indications supplémentaires liées aux opérandes */
@@ -58,6 +54,41 @@ typedef enum _ArchOperandFlag
#define AOF_USER_FLAG(n) (1 << (AOF_USER_BIT + n))
+/* Ajoute une information complémentaire à un opérande. */
+bool g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag);
+
+/* Retire une information complémentaire à un opérande. */
+bool g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag);
+
+/* Détermine si un opérande possède un fanion particulier. */
+bool g_arch_operand_has_flag(const GArchOperand *, ArchOperandFlag);
+
+/* Fournit les particularités de l'opérande. */
+ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *);
+
+
+
+
+#if 0
+
+
+#include <glib-object.h>
+
+
+#include "../common/packed.h"
+#include "../format/format.h"
+#include "../glibext/bufferline.h"
+
+
+
+/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */
+
+
+/* Depuis "../analysis/binary.h" : description de fichier binaire */
+typedef struct _GLoadedBinary GLoadedBinary;
+
+
+
#define G_TYPE_ARCH_OPERAND g_arch_operand_get_type()
#define G_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_OPERAND, GArchOperand))
#define G_IS_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_OPERAND))
@@ -95,18 +126,6 @@ char *g_arch_operand_build_tooltip(const GArchOperand *, const GLoadedBinary *);
#endif
-/* Ajoute une information complémentaire à un opérande. */
-bool g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag);
-
-/* Retire une information complémentaire à un opérande. */
-bool g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag);
-
-/* Détermine si un opérande possède un fanion particulier. */
-bool g_arch_operand_has_flag(const GArchOperand *, ArchOperandFlag);
-
-/* Fournit les particularités de l'opérande. */
-ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *);
-
/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
@@ -116,5 +135,8 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *);
typedef struct _GAsmStorage GAsmStorage;
+#endif
+
+
#endif /* _ARCH_OPERAND_H */
diff --git a/src/arch/operands/Makefile.am b/src/arch/operands/Makefile.am
index f2a8767..3d9cbde 100644
--- a/src/arch/operands/Makefile.am
+++ b/src/arch/operands/Makefile.am
@@ -1,26 +1,36 @@
-noinst_LTLIBRARIES = libarchoperands.la
+noinst_LTLIBRARIES = libarchoperands.la libarchoperandsui.la
+
+# libarchoperands_la_SOURCES = \
+# feeder-int.h \
+# feeder.h feeder.c \
+# proxy-int.h \
+# proxy.h proxy.c \
+# rename-int.h \
+# rename.h rename.c \
+# target-int.h \
+# target.h target.c \
+# targetable-int.h \
+# targetable.h targetable.c
libarchoperands_la_SOURCES = \
- feeder-int.h \
- feeder.h feeder.c \
immediate-int.h \
immediate.h immediate.c \
+ known-int.h \
known.h known.c \
register-int.h \
- register.h register.c \
- proxy-int.h \
- proxy.h proxy.c \
- rename-int.h \
- rename.h rename.c \
- target-int.h \
- target.h target.c \
- targetable-int.h \
- targetable.h targetable.c
+ register.h register.c
+
+libarchoperands_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+libarchoperandsui_la_SOURCES = \
+ immediate-ui.h immediate-ui.c \
+ known-ui.h known-ui.c \
+ register-ui.h register-ui.c
-libarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+libarchoperandsui_la_CFLAGS = $(LIBGTK4_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
-dev_HEADERS = $(libarchoperands_la_SOURCES:%c=)
+dev_HEADERS = $(libarchoperands_la_SOURCES:%c=) $(libarchoperandsui_la_SOURCES:%c=)
diff --git a/src/arch/operands/immediate-int.h b/src/arch/operands/immediate-int.h
index d2313f5..3d60c7d 100644
--- a/src/arch/operands/immediate-int.h
+++ b/src/arch/operands/immediate-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* immediate-int.h - définitions internes propres aux opérandes représentant des valeurs numériques
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -30,27 +30,8 @@
-/* Informations glissées dans la structure GObject de GArchOperand */
-typedef struct _immop_extra_data_t
-{
- operand_extra_data_t parent; /* A laisser en premier */
-
- MemoryDataSize size; /* Taille de l'opérande */
-
- /**
- * Les deux éléments suivants sont de type ImmOperandDisplay ;
- * leur espace de conservation est réduit au maximum afin d'éviter
- * un recouvrement .
- */
-
- unsigned int def_display : 3; /* Type par défaut d'affichage */
- unsigned int display : 3; /* Format général d'affichage */
-
-} immop_extra_data_t;
-
-
/* Définition d'un opérande de valeur numérique (instance) */
-struct _GImmOperand
+struct _GImmediateOperand
{
GArchOperand parent; /* Instance parente */
@@ -59,7 +40,7 @@ struct _GImmOperand
};
/* Définition d'un opérande de valeur numérique (classe) */
-struct _GImmOperandClass
+struct _GImmediateOperandClass
{
GArchOperandClass parent; /* Classe parente */
@@ -70,15 +51,46 @@ struct _GImmOperandClass
* Accès aux informations éventuellement déportées.
*/
-#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__
+/* Informations glissées dans la structure GObject de GArchOperand */
+typedef struct _immop_extra_data_t
+{
+ ARCH_OPERAND_EXTRA_DATA(3); /* Informations pour l'opérande*/
-# define GET_IMM_OP_EXTRA(op) ((immop_extra_data_t *)&((GArchOperand *)op)->extra)
+ /**
+ * MemoryDataSize
+ */
+ unsigned int size : 4; /* Taille de l'opérande */
+
+ /**
+ * ImmOperandDisplay x 2
+ */
+ unsigned int def_display : 3; /* Type par défaut d'affichage */
+ unsigned int display : 3; /* Format général d'affichage */
+
+} immop_extra_data_t;
+
+
+#define GET_IMM_OP_EXTRA(op) \
+ GET_GOBJECT_EXTRA(op, immop_extra_data_t)
+
+#define SET_IMM_OP_EXTRA(op, data) \
+ SET_GOBJECT_EXTRA(op, immop_extra_data_t, data)
-#else
-# define GET_IMM_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), immop_extra_data_t)
+/* Met en place un opérande réprésentant une valeur numérique. */
+bool g_immediate_operand_create_from_value(GImmediateOperand *, MemoryDataSize, uint64_t);
+
+/* Crée un opérande réprésentant une valeur numérique. */
+bool g_immediate_operand_create_from_data(GImmediateOperand *, MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian);
+
+/**
+ * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE,
+ * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire.
+ */
+#define IMM_MAX_SIZE 66
-#endif
+/* Construit la chaîne de caractères correspondant à l'opérande. */
+size_t _g_immediate_operand_to_string(const GImmediateOperand *, ImmOperandDisplay, char [IMM_MAX_SIZE]);
diff --git a/src/arch/operands/immediate-ui.c b/src/arch/operands/immediate-ui.c
new file mode 100644
index 0000000..62058b3
--- /dev/null
+++ b/src/arch/operands/immediate-ui.c
@@ -0,0 +1,184 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * immediate-ui.c - opérandes représentant des valeurs numériques sous forme graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "immediate-ui.h"
+
+
+#include <i18n.h>
+
+
+#include "immediate-int.h"
+#include "../../common/extstr.h"
+#include "../../glibext/tokenstyle.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Traduit un opérande en version humainement lisible. */
+static void g_immediate_operand_ui_print(const GImmediateOperand *, GBufferLine *);
+
+/* Construit un petit résumé concis de l'opérande. */
+static char *g_immediate_operand_ui_build_tooltip(const GImmediateOperand *, const GLoadedBinary *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'opérande UI. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface)
+{
+ iface->print = (print_operand_ui_fc)g_immediate_operand_ui_print;
+ iface->build_tooltip = (build_operand_ui_tooltip_fc)g_immediate_operand_ui_build_tooltip;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_immediate_operand_ui_print(const GImmediateOperand *operand, GBufferLine *line)
+{
+ GImmediateOperand *base; /* Version d'instance basique */
+ ImmOperandDisplay display; /* Type d'affichage courant */
+ char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */
+ size_t len; /* Taille de l'élément inséré */
+
+ base = G_IMMEDIATE_OPERAND(operand);
+
+ display = g_immediate_operand_get_display(base);
+
+ len = _g_immediate_operand_to_string(base, display, value);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_IMMEDIATE, value, len, NULL, G_OBJECT(operand));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* binary = informations relatives au binaire chargé. *
+* *
+* Description : Construit un petit résumé concis de l'opérande. *
+* *
+* Retour : Chaîne de caractères à libérer après usage ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_immediate_operand_ui_build_tooltip(const GImmediateOperand *operand, const GLoadedBinary *binary)
+{
+ char *result; /* Description à retourner */
+ GImmediateOperand *base; /* Version d'instance basique */
+ char value[IMM_MAX_SIZE]; /* Conversion artificielle */
+ char *conv; /* Affichage de la Conversion */
+
+ base = G_IMMEDIATE_OPERAND(operand);
+
+ if (base->raw <= UCHAR_MAX && isprint(base->raw))
+ switch (base->raw)
+ {
+ case '&':
+ asprintf(&result, _("Character: '&amp;'"));
+ break;
+ case '<':
+ asprintf(&result, _("Character: '&lt;'"));
+ break;
+ case '>':
+ asprintf(&result, _("Character: '&gt;'"));
+ break;
+ default:
+ asprintf(&result, _("Character: '%c'"), (char)base->raw);
+ break;
+ }
+
+ else
+ asprintf(&result, _("Character: &lt;not printable&gt;"));
+
+ /* Binaire */
+
+ _g_immediate_operand_to_string(base, IOD_BIN, value);
+
+ asprintf(&conv, _("Binary: %s"), value);
+
+ result = stradd(result, "\n");
+ result = stradd(result, conv);
+
+ free(conv);
+
+ /* Octal */
+
+ _g_immediate_operand_to_string(base, IOD_OCT, value);
+
+ asprintf(&conv, _("Octal: %s"), value);
+
+ result = stradd(result, "\n");
+ result = stradd(result, conv);
+
+ free(conv);
+
+ /* Décimal */
+
+ _g_immediate_operand_to_string(base, IOD_DEC, value);
+
+ asprintf(&conv, _("Decimal: %s"), value);
+
+ result = stradd(result, "\n");
+ result = stradd(result, conv);
+
+ free(conv);
+
+ /* Hexadécimal */
+
+ _g_immediate_operand_to_string(base, IOD_HEX, value);
+
+ asprintf(&conv, _("Hexadecimal: %s"), value);
+
+ result = stradd(result, "\n");
+ result = stradd(result, conv);
+
+ free(conv);
+
+ return result;
+
+}
diff --git a/src/arch/operands/immediate-ui.h b/src/arch/operands/immediate-ui.h
new file mode 100644
index 0000000..4dbddae
--- /dev/null
+++ b/src/arch/operands/immediate-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * immediate-ui.h - prototypes pour les opérandes représentant des valeurs numériques sous forme graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_IMMEDIATE_UI_H
+#define _ARCH_OPERANDS_IMMEDIATE_UI_H
+
+
+#include "../operand-ui-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface d'opérande UI. */
+void g_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_IMMEDIATE_UI_H */
diff --git a/src/arch/operands/immediate.c b/src/arch/operands/immediate.c
index f40c645..f99b421 100644
--- a/src/arch/operands/immediate.c
+++ b/src/arch/operands/immediate.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* immediate.c - opérandes représentant des valeurs numériques
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,25 +25,32 @@
#include <assert.h>
+#include <stdarg.h>
+
+
+
+#if 0
+
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <malloc.h>
-#include <stdarg.h>
#include <stdio.h>
#include <i18n.h>
+#endif
+
+
#include "immediate-int.h"
-#include "known.h"
-#include "rename-int.h"
-#include "targetable-int.h"
#include "../../common/asm.h"
-#include "../../common/extstr.h"
#include "../../common/sort.h"
-#include "../../core/columns.h"
+#include "../../glibext/comparable-int.h"
+#include "../../glibext/hashable-int.h"
+#include "../../glibext/serialize-int.h"
+#include "../../glibext/strbuilder-int.h"
@@ -51,68 +58,75 @@
/* Initialise la classe des opérandes de valeur immédiate. */
-static void g_imm_operand_class_init(GImmOperandClass *);
+static void g_immediate_operand_class_init(GImmediateOperandClass *);
-/* Initialise un opérande de valeur immédiate. */
-static void g_imm_operand_init(GImmOperand *);
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_immediate_operand_string_builder_iface_init(GStringBuilderInterface *, gpointer);
+
+#if 0
/* Procède à l'initialisation de l'interface de ciblage. */
-static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface *);
+static void g_immediate_operand_targetable_interface_init(GTargetableOperandInterface *);
/* Procède à l'initialisation de l'interface de renommage. */
-static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface *);
+static void g_immediate_operand_renameable_interface_init(GRenameableOperandInterface *);
+
+#endif
+
+/* Initialise un opérande de valeur immédiate. */
+static void g_immediate_operand_init(GImmediateOperand *);
/* Supprime toutes les références externes. */
-static void g_imm_operand_dispose(GImmOperand *);
+static void g_immediate_operand_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_imm_operand_finalize(GImmOperand *);
+static void g_immediate_operand_finalize(GObject *);
-/* Construit la chaîne de caractères correspondant à l'opérande. */
-static size_t _g_imm_operand_to_string(const GImmOperand *, ImmOperandDisplay, char [IMM_MAX_SIZE]);
-/* Traduit un opérande en version humainement lisible. */
-static void g_imm_operand_print(const GImmOperand *, GBufferLine *);
+/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Réalise une comparaison étendue entre objets. */
+static int g_immediate_operand_compare(const GComparableObject *, const GComparableObject *);
-/* Compare un opérande avec un autre. */
-static int g_imm_operand_compare(const GImmOperand *, const GImmOperand *, bool);
-#ifdef INCLUDE_GTK_SUPPORT
+/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */
-/* Construit un petit résumé concis de l'opérande. */
-static char *g_imm_operand_build_tooltip(const GImmOperand *, const GLoadedBinary *);
-#endif
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+static guint g_immediate_operand_hash(const GHashableObject *);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint g_imm_operand_hash(const GImmOperand *, bool);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_imm_operand_load(GImmOperand *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_imm_operand_store(GImmOperand *, GObjectStorage *, packed_buffer_t *);
+/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
+/* Charge un objet depuis un flux de données. */
+static bool g_immediate_operand_load(GSerializableObject *, GObjectStorage *, int);
-/* ---------------------- COMMUNICATION D'UN CIBLAGE POTENTIEL ---------------------- */
+/* Sauvegarde un objet dans un flux de données. */
+static bool g_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int);
-/* Obtient l'adresse de la cible visée par un opérande. */
-static bool g_imm_operand_get_addr(const GImmOperand *, const vmpa2t *, GBinFormat *, GArchProcessor *, vmpa2t *);
+/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */
-/* ---------------------- CONSTRUCTION D'UN CONTENU ALTERNATIF ---------------------- */
+/* Exporte une chaîne de caractères à partir d'un objet. */
+static bool g_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
-/* Construit un opérande de représentation alternative. */
-static GRenamedOperand *g_imm_operand_build(const GImmOperand *, const char *);
@@ -122,9 +136,12 @@ static GRenamedOperand *g_imm_operand_build(const GImmOperand *, const char *);
/* Indique le type défini pour un opérande de valeur numérique. */
-G_DEFINE_TYPE_WITH_CODE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND,
- G_IMPLEMENT_INTERFACE(G_TYPE_TARGETABLE_OPERAND, g_imm_operand_targetable_interface_init)
- G_IMPLEMENT_INTERFACE(G_TYPE_RENAMEABLE_OPERAND, g_imm_operand_renameable_interface_init));
+G_DEFINE_TYPE_WITH_CODE(GImmediateOperand, g_immediate_operand, G_TYPE_ARCH_OPERAND,
+ G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_immediate_operand_comparable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_immediate_operand_hashable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_immediate_operand_serializable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_immediate_operand_string_builder_iface_init)
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_immediate_operand_ui_arch_operand_ui_iface_init));
/******************************************************************************
@@ -139,36 +156,42 @@ G_DEFINE_TYPE_WITH_CODE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND,
* *
******************************************************************************/
-static void g_imm_operand_class_init(GImmOperandClass *klass)
+static void g_immediate_operand_class_init(GImmediateOperandClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_imm_operand_dispose;
- object->finalize = (GObjectFinalizeFunc)g_imm_operand_finalize;
+ object->dispose = g_immediate_operand_dispose;
+ object->finalize = g_immediate_operand_finalize;
- operand->compare = (operand_compare_fc)g_imm_operand_compare;
- operand->print = (operand_print_fc)g_imm_operand_print;
-#ifdef INCLUDE_GTK_SUPPORT
- operand->build_tooltip = (operand_build_tooltip_fc)g_imm_operand_build_tooltip;
-#endif
+}
- operand->hash = (operand_hash_fc)g_imm_operand_hash;
- operand->load = (load_operand_fc)g_imm_operand_load;
- operand->store = (store_operand_fc)g_imm_operand_store;
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface)
+{
+ iface->compare = g_immediate_operand_compare;
}
/******************************************************************************
* *
-* Paramètres : operand = instance à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Initialise un opérande de valeur immédiate. *
+* Description : Procède à l'initialisation de l'interface de détermination. *
* *
* Retour : - *
* *
@@ -176,23 +199,39 @@ static void g_imm_operand_class_init(GImmOperandClass *klass)
* *
******************************************************************************/
-static void g_imm_operand_init(GImmOperand *operand)
+static void g_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface)
{
- GET_IMM_OP_EXTRA(operand)->size = MDS_UNDEFINED;
+ iface->hash = g_immediate_operand_hash;
- GET_IMM_OP_EXTRA(operand)->def_display = IOD_HEX;
- GET_IMM_OP_EXTRA(operand)->display = IOD_COUNT;
+}
- operand->raw = 0;
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de sérialisation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *iface)
+{
+ iface->load = g_immediate_operand_load;
+ iface->store = g_immediate_operand_store;
}
/******************************************************************************
* *
-* Paramètres : iface = interface GLib à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
+* unused = pointeur non utilisé ici. *
* *
-* Description : Procède à l'initialisation de l'interface de ciblage. *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
* *
* Retour : - *
* *
@@ -200,18 +239,18 @@ static void g_imm_operand_init(GImmOperand *operand)
* *
******************************************************************************/
-static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface *iface)
+static void g_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface, gpointer unused)
{
- iface->get_addr = (get_targetable_addr_fc)g_imm_operand_get_addr;
+ iface->to_string = g_immediate_operand_to_string;
}
/******************************************************************************
* *
-* Paramètres : iface = interface GLib à initialiser. *
+* Paramètres : operand = instance à initialiser. *
* *
-* Description : Procède à l'initialisation de l'interface de renommage. *
+* Description : Initialise un opérande de valeur immédiate. *
* *
* Retour : - *
* *
@@ -219,16 +258,27 @@ static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface
* *
******************************************************************************/
-static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface *iface)
+static void g_immediate_operand_init(GImmediateOperand *operand)
{
- iface->build = (build_renameable_fc)g_imm_operand_build;
+ immop_extra_data_t extra; /* Données insérées à consulter*/
+
+ extra = GET_IMM_OP_EXTRA(operand);
+
+ extra.size = MDS_UNDEFINED;
+
+ extra.def_display = IOD_HEX;
+ extra.display = IOD_COUNT;
+
+ SET_IMM_OP_EXTRA(operand, &extra);
+
+ operand->raw = 0;
}
/******************************************************************************
* *
-* Paramètres : operand = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -238,16 +288,16 @@ static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface
* *
******************************************************************************/
-static void g_imm_operand_dispose(GImmOperand *operand)
+static void g_immediate_operand_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_imm_operand_parent_class)->dispose(G_OBJECT(operand));
+ G_OBJECT_CLASS(g_immediate_operand_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : operand = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -257,9 +307,74 @@ static void g_imm_operand_dispose(GImmOperand *operand)
* *
******************************************************************************/
-static void g_imm_operand_finalize(GImmOperand *operand)
+static void g_immediate_operand_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(g_immediate_operand_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : size = taille de l'opérande souhaitée. *
+* value = valeur sur x bits à venir récupérer. *
+* *
+* Description : Crée un opérande réprésentant une valeur numérique. *
+* *
+* Retour : Instruction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_immediate_operand_new_from_value(MemoryDataSize size, uint64_t value)
{
- G_OBJECT_CLASS(g_imm_operand_parent_class)->finalize(G_OBJECT(operand));
+ GImmediateOperand *result; /* Opérande à retourner */
+
+ result = g_object_new(G_TYPE_IMMEDIATE_OPERAND, NULL);
+
+ if (!g_immediate_operand_create_from_value(result, size, value))
+ g_clear_object(&result);
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser pleinement. *
+* size = taille de l'opérande souhaitée. *
+* value = valeur sur x bits à venir récupérer. *
+* *
+* Description : Met en place un opérande réprésentant une valeur numérique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_immediate_operand_create_from_value(GImmediateOperand *operand, MemoryDataSize size, uint64_t value)
+{
+ bool result; /* Bilan à retourner */
+ immop_extra_data_t extra; /* Données insérées à consulter*/
+
+ result = (size != MDS_UNDEFINED);
+
+ if (result)
+ {
+ extra = GET_IMM_OP_EXTRA(operand);
+
+ extra.size = size;
+
+ operand->raw = value;
+
+ SET_IMM_OP_EXTRA(operand, &extra);
+
+ }
+
+ return result;
}
@@ -280,10 +395,41 @@ static void g_imm_operand_finalize(GImmOperand *operand)
* *
******************************************************************************/
-GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian)
+GArchOperand *g_immediate_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian)
{
- GImmOperand *result; /* Opérande à retourner */
- immop_extra_data_t *extra; /* Données insérées à modifier */
+ GImmediateOperand *result; /* Opérande à retourner */
+
+ result = g_object_new(G_TYPE_IMMEDIATE_OPERAND, NULL);
+
+ if (!g_immediate_operand_create_from_data(result, size, content, addr, low, endian))
+ g_clear_object(&result);
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser pleinement. *
+* size = taille de l'opérande souhaitée. *
+* content = flux de données à analyser. *
+* addr = position courante dans ce flux. [OUT] *
+* low = position éventuelle des 4 bits visés. [OUT] *
+* endian = ordre des bits dans la source. *
+* *
+* Description : Crée un opérande réprésentant une valeur numérique. *
+* *
+* Retour : Instruction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_immediate_operand_create_from_data(GImmediateOperand *operand, MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian)
+{
+ bool result; /* Bilan à retourner */
+ uint64_t raw; /* Valeur brute lue */
uint8_t uval8; /* Valeur sur 8 bits */
uint16_t uval16; /* Valeur sur 16 bits */
uint32_t uval32; /* Valeur sur 32 bits */
@@ -293,125 +439,78 @@ GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinConten
int32_t sval32; /* Valeur sur 32 bits */
int64_t sval64; /* Valeur sur 64 bits */
- result = g_object_new(G_TYPE_IMM_OPERAND, NULL);
-
- extra = GET_IMM_OP_EXTRA(result);
-
- extra->size = size;
-
switch (size)
{
case MDS_4_BITS_UNSIGNED:
- if (!g_binary_content_read_u4(content, addr, low, &uval8))
- goto gionfd_error;
- result->raw = uval8;
+ result = g_binary_content_read_u4(content, addr, low, &uval8);
+ if (result)
+ raw = uval8;
break;
case MDS_8_BITS_UNSIGNED:
- if (!g_binary_content_read_u8(content, addr, &uval8))
- goto gionfd_error;
- result->raw = uval8;
+ result = g_binary_content_read_u8(content, addr, &uval8);
+ if (result)
+ raw = uval8;
break;
case MDS_16_BITS_UNSIGNED:
- if (!g_binary_content_read_u16(content, addr, endian, &uval16))
- goto gionfd_error;
- result->raw = uval16;
+ result = g_binary_content_read_u16(content, addr, endian, &uval16);
+ if (result)
+ raw = uval16;
break;
case MDS_32_BITS_UNSIGNED:
- if (!g_binary_content_read_u32(content, addr, endian, &uval32))
- goto gionfd_error;
- result->raw = uval32;
+ result = g_binary_content_read_u32(content, addr, endian, &uval32);
+ if (result)
+ raw = uval32;
break;
case MDS_64_BITS_UNSIGNED:
- if (!g_binary_content_read_u64(content, addr, endian, &uval64))
- goto gionfd_error;
- result->raw = uval64;
+ result = g_binary_content_read_u64(content, addr, endian, &uval64);
+ if (result)
+ raw = uval64;
break;
case MDS_4_BITS_SIGNED:
- if (!g_binary_content_read_s4(content, addr, low, &sval8))
- goto gionfd_error;
- result->raw = sval8;
+ result = g_binary_content_read_s4(content, addr, low, &sval8);
+ if (result)
+ raw = sval8;
break;
case MDS_8_BITS_SIGNED:
- if (!g_binary_content_read_s8(content, addr, &sval8))
- goto gionfd_error;
- result->raw = sval8;
+ result = g_binary_content_read_s8(content, addr, &sval8);
+ if (result)
+ raw = sval8;
break;
case MDS_16_BITS_SIGNED:
- if (!g_binary_content_read_s16(content, addr, endian, &sval16))
- goto gionfd_error;
- result->raw = sval16;
+ result = g_binary_content_read_s16(content, addr, endian, &sval16);
+ if (result)
+ raw = sval16;
break;
case MDS_32_BITS_SIGNED:
- if (!g_binary_content_read_s32(content, addr, endian, &sval32))
- goto gionfd_error;
- result->raw = sval32;
+ result = g_binary_content_read_s32(content, addr, endian, &sval32);
+ if (result)
+ raw = sval32;
break;
case MDS_64_BITS_SIGNED:
- if (!g_binary_content_read_s64(content, addr, endian, &sval64))
- goto gionfd_error;
- result->raw = sval64;
+ result = g_binary_content_read_s64(content, addr, endian, &sval64);
+ if (result)
+ raw = sval64;
break;
case MDS_UNDEFINED:
- goto gionfd_error;
+ result = false;
break;
}
- return G_ARCH_OPERAND(result);
-
- gionfd_error:
-
- g_object_unref(G_OBJECT(result));
-
- return NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : size = taille de l'opérande souhaitée. *
-* value = valeur sur x bits à venir récupérer. *
-* *
-* Description : Crée un opérande réprésentant une valeur numérique. *
-* *
-* Retour : Instruction mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value)
-{
- GImmOperand *result; /* Opérande à retourner */
- immop_extra_data_t *extra; /* Données insérées à modifier */
-
- if (size == MDS_UNDEFINED)
- result = NULL;
-
- else
- {
- result = g_object_new(G_TYPE_IMM_OPERAND, NULL);
-
- extra = GET_IMM_OP_EXTRA(result);
-
- extra->size = size;
-
- result->raw = value;
-
- }
+ if (result)
+ result = g_immediate_operand_create_from_value(operand, size, raw);
- return (result != NULL ? G_ARCH_OPERAND(result) : NULL);
+ return result;
}
@@ -428,18 +527,14 @@ GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value)
* *
******************************************************************************/
-MemoryDataSize g_imm_operand_get_size(const GImmOperand *operand)
+MemoryDataSize g_immediate_operand_get_size(const GImmediateOperand *operand)
{
MemoryDataSize result; /* Taille à retourner */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->size;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.size;
return result;
@@ -460,10 +555,10 @@ MemoryDataSize g_imm_operand_get_size(const GImmOperand *operand)
* *
******************************************************************************/
-bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ...)
+bool g_immediate_operand_get_value(const GImmediateOperand *operand, MemoryDataSize size, ...)
{
bool result; /* Bilan à retourner */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
va_list ap; /* Liste des compléments */
uint8_t *uval8; /* Valeur sur 8 bits */
uint16_t *uval16; /* Valeur sur 16 bits */
@@ -478,9 +573,7 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ..
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- if (extra->size != size)
+ if (extra.size != size)
goto exit;
va_start(ap, size);
@@ -533,8 +626,6 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ..
exit:
- UNLOCK_GOBJECT_EXTRA(extra);
-
return result;
}
@@ -542,6 +633,37 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ..
/******************************************************************************
* *
+* Paramètres : operand = structure dont le contenu est à actualiser. [OUT] *
+* size = taille de l'opérande souhaitée. *
+* value = valeur sur x bits à venir récupérer. *
+* *
+* Description : Définit la nouvelle valeur de l'opérande à une valeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_immediate_operand_set_value(GImmediateOperand *operand, MemoryDataSize size, uint64_t value)
+{
+ immop_extra_data_t extra; /* Données insérées à consulter*/
+
+ assert(size != MDS_UNDEFINED);
+
+ extra = GET_IMM_OP_EXTRA(operand);
+
+ extra.size = size;
+
+ operand->raw = value;
+
+ SET_IMM_OP_EXTRA(operand, &extra);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à consulter. *
* *
* Description : Fournit la valeur brute représentée par l'opérande. *
@@ -552,42 +674,55 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ..
* *
******************************************************************************/
-uint64_t g_imm_operand_get_raw_value(const GImmOperand *operand)
+uint64_t g_immediate_operand_get_raw_value(const GImmediateOperand *operand)
{
- return operand->raw;
+ uint64_t result; /* Valeur brute à retourner */
+
+ result = operand->raw;
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : operand = structure dont le contenu est à actualiser. [OUT] *
-* size = taille de l'opérande souhaitée. *
-* value = valeur sur x bits à venir récupérer. *
+* Paramètres : operand = structure dont le contenu est à consulter. *
* *
-* Description : Définit la nouvelle valeur de l'opérande à une valeur. *
+* Description : Indique le signe d'une valeur immédiate. *
* *
-* Retour : - *
+* Retour : true si la valeur est strictement négative, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t value)
+bool g_immediate_operand_is_negative(const GImmediateOperand *operand)
{
- immop_extra_data_t *extra; /* Données insérées à consulter*/
-
- assert(size != MDS_UNDEFINED);
+ bool result; /* Bilan à renvoyer */
+ immop_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- extra->size = size;
-
- operand->raw = value;
+ switch (extra.size)
+ {
+ case MDS_4_BITS_SIGNED:
+ case MDS_8_BITS_SIGNED:
+ case MDS_16_BITS_SIGNED:
+ case MDS_32_BITS_SIGNED:
+ case MDS_64_BITS_SIGNED:
+ /**
+ * Pour les valeurs plus petites que 64 bits, le compilateur
+ * réalise une extension de signe lors du transtypage.
+ */
+ result = (operand->raw & 0x8000000000000000ll);
+ break;
+ default:
+ result = false;
+ break;
+ }
- UNLOCK_GOBJECT_EXTRA(extra);
+ return result;
}
@@ -605,17 +740,15 @@ void g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t
* *
******************************************************************************/
-void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay display)
+void g_immediate_operand_set_default_display(GImmediateOperand *operand, ImmOperandDisplay display)
{
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
+ extra.def_display = display;
- extra->def_display = display;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ SET_IMM_OP_EXTRA(operand, &extra);
}
@@ -632,18 +765,14 @@ void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay d
* *
******************************************************************************/
-ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand)
+ImmOperandDisplay g_immediate_operand_get_default_display(const GImmediateOperand *operand)
{
ImmOperandDisplay result; /* Affichage à retourner */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- result = extra->def_display;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.def_display;
return result;
@@ -663,17 +792,15 @@ ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand)
* *
******************************************************************************/
-void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display)
+void g_immediate_operand_set_display(GImmediateOperand *operand, ImmOperandDisplay display)
{
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
+ extra.display = display;
- extra->display = display;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ SET_IMM_OP_EXTRA(operand, &extra);
}
@@ -690,94 +817,225 @@ void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display)
* *
******************************************************************************/
-ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *operand)
+ImmOperandDisplay g_immediate_operand_get_display(const GImmediateOperand *operand)
{
ImmOperandDisplay result; /* Affichage à retourner */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
extra = GET_IMM_OP_EXTRA(operand);
- LOCK_GOBJECT_EXTRA(extra);
-
- if (extra->display != IOD_COUNT)
- result = extra->display;
+ if (extra.display != IOD_COUNT)
+ result = extra.display;
else
- result = extra->def_display;
-
- UNLOCK_GOBJECT_EXTRA(extra);
+ result = extra.def_display;
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* COMPARAISON DETAILLEE DE DEUX OBJETS */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = structure dont le contenu est à consulter. *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
* *
-* Description : Indique le signe d'une valeur immédiate. *
+* Description : Réalise une comparaison étendue entre objets. *
* *
-* Retour : true si la valeur est strictement négative, false sinon. *
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_imm_operand_is_negative(const GImmOperand *operand)
+static int g_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other)
{
- bool result; /* Bilan à renvoyer */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ int result; /* Bilan à retourner */
+ GComparableObjectInterface *iface; /* Interface utilisée */
+ GComparableObjectInterface *parent_iface; /* Interface parente */
+ GImmediateOperand *operand_a; /* Version spécialisée #0 */
+ GImmediateOperand *operand_b; /* Version spécialisée #1 */
+ immop_extra_data_t extra_a; /* Données insérées à consulter*/
+ immop_extra_data_t extra_b; /* Données insérées à consulter*/
- extra = GET_IMM_OP_EXTRA(operand);
+ iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
+
+ parent_iface = g_type_interface_peek_parent(iface);
- LOCK_GOBJECT_EXTRA(extra);
+ result = parent_iface->compare(object, other);
- switch (extra->size)
+ if (result == 0)
{
- case MDS_4_BITS_SIGNED:
- case MDS_8_BITS_SIGNED:
- case MDS_16_BITS_SIGNED:
- case MDS_32_BITS_SIGNED:
- case MDS_64_BITS_SIGNED:
- /**
- * Pour les valeurs plus petites que 64 bits, le compilateur
- * réalise une extension de signe lors du transtypage.
- */
- result = (operand->raw & 0x8000000000000000ll);
- break;
- default:
- result = false;
- break;
+ operand_a = G_IMMEDIATE_OPERAND(object);
+
+ extra_a = GET_IMM_OP_EXTRA(operand_a);
+
+ operand_b = G_IMMEDIATE_OPERAND(other);
+
+ extra_b = GET_IMM_OP_EXTRA(operand_b);
+
+ result = sort_unsigned_long(extra_a.size, extra_b.size);
+
+ if (result == 0)
+ sort_uint64_t(operand_a->raw, operand_b->raw);
+
+ if (result == 0)
+ result = sort_unsigned_long(extra_a.def_display, extra_b.def_display);
+
+ if (result == 0)
+ result = sort_unsigned_long(extra_a.display, extra_b.display);
+
}
- UNLOCK_GOBJECT_EXTRA(extra);
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = objet dont l'instance est à consulter. *
+* *
+* Description : Calcule l'empreinte sur 32 bits d'un objet. *
+* *
+* Retour : Valeur de représentation, unique pour l'objet ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static guint g_immediate_operand_hash(const GHashableObject *object)
+{
+ guint result; /* Valeur à retourner */
+ GHashableObjectInterface *iface; /* Interface utilisée */
+ GHashableObjectInterface *parent_iface; /* Interface parente */
+ GImmediateOperand *operand; /* Version spécialisée */
+
+ iface = G_HASHABLE_OBJECT_GET_IFACE(object);
+
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ result = parent_iface->hash(object);
+
+ operand = G_IMMEDIATE_OPERAND(object);
+
+ result ^= (operand->raw & 0xffffffff);
+ result ^= (operand->raw >> 32);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE CONSERVATION ET RESTAURATION */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = structure dont le contenu est à consulter. *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Indique si une valeur immédiate est nulle ou non. *
+* Description : Charge un objet depuis un flux de données. *
* *
-* Retour : true si la valeur est nulle, false sinon. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_imm_operand_is_null(const GImmOperand *operand)
+static bool g_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
- return (operand->raw == 0ll);
+ bool result; /* Bilan à retourner */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *parent_iface; /* Interface parente */
+ uleb128_t val; /* Valeur sauvegardée */
+ GImmediateOperand *operand; /* Version spécialisée */
+
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
+
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ result = parent_iface->load(object, storage, fd);
+
+ if (result)
+ {
+ result = load_uleb128(&val, fd);
+
+ if (result)
+ {
+ operand = G_IMMEDIATE_OPERAND(object);
+ operand->raw = val;
+ }
+
+ }
+
+ return result;
}
/******************************************************************************
* *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
+* *
+* Description : Sauvegarde un objet dans un flux de données. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
+{
+ bool result; /* Bilan à retourner */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *parent_iface; /* Interface parente */
+ GImmediateOperand *operand; /* Version spécialisée */
+
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
+
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ result = parent_iface->store(object, storage, fd);
+ if (!result) goto exit;
+
+ operand = G_IMMEDIATE_OPERAND(object);
+
+ result = store_uleb128((uleb128_t []) { operand->raw }, fd);
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à transcrire. *
* display = type d'affichage demandé. *
* value = valeur portée par l'opérande transcrite. [OUT] *
@@ -790,10 +1048,10 @@ bool g_imm_operand_is_null(const GImmOperand *operand)
* *
******************************************************************************/
-static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDisplay display, char value[IMM_MAX_SIZE])
+size_t _g_immediate_operand_to_string(const GImmediateOperand *operand, ImmOperandDisplay display, char value[IMM_MAX_SIZE])
{
size_t result; /* Longueur à retourner */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
+ immop_extra_data_t extra; /* Données insérées à consulter*/
unsigned int range; /* Catégorie de la taille */
const char *prefix; /* Entrée en matière */
const char *suffix; /* Sortie de matière */
@@ -813,13 +1071,11 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis
static const char *conv_si_defs[] = { "", "o", "d", "x", "c" };
static const char *conv_us_defs[] = { "", "o", "u", "x", "c" };
- assert(display <= IOD_LAST_VALID);
+ assert(display < IOD_COUNT);
extra = GET_IMM_OP_EXTRA(operand);
- //LOCK_GOBJECT_EXTRA(extra);
-
- range = MDS_RANGE(extra->size);
+ range = MDS_RANGE(extra.size);
/* Encadrement pour les caractères */
if (display == IOD_CHAR)
@@ -862,10 +1118,10 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis
if (do_padding)
{
- if (extra->display != IOD_COUNT)
- do_padding = (extra->display != IOD_BIN && extra->display != IOD_HEX);
+ if (extra.display != IOD_COUNT)
+ do_padding = (extra.display == IOD_BIN || extra.display == IOD_HEX);
else
- do_padding = (extra->def_display != IOD_BIN && extra->def_display != IOD_HEX);
+ do_padding = (extra.def_display == IOD_BIN || extra.def_display == IOD_HEX);
}
switch (display)
@@ -892,7 +1148,7 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis
if (display != IOD_BIN)
{
- if (MDS_IS_SIGNED(extra->size))
+ if (MDS_IS_SIGNED(extra.size))
conv = conv_si_defs[display];
else
conv = conv_us_defs[display];
@@ -929,7 +1185,7 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis
snprintf(format, sizeof(format), "%s%s%s%s%s%s%s", prefix, alternate, intro, zpad, lmod, conv, suffix);
- switch (extra->size)
+ switch (extra.size)
{
case MDS_UNDEFINED:
result = snprintf(value, IMM_MAX_SIZE, "<? undef value ?>");
@@ -982,8 +1238,6 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis
}
- //UNLOCK_GOBJECT_EXTRA(extra);
-
assert(result > 0);
return result;
@@ -993,555 +1247,37 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis
/******************************************************************************
* *
-* Paramètres : operand = opérande à transcrire. *
-* syntax = type de représentation demandée. *
-* value = valeur portée par l'opérande transcrite. [OUT] *
+* Paramètres : builder = objet dont l'instance est exportable. *
+* flags = éventuelles indications pour l'opération. *
+* out = chaîne de caractères mise en place. [OUT] *
* *
-* Description : Construit la chaîne de caractères correspondant à l'opérande.*
+* Description : Exporte une chaîne de caractères à partir d'un objet. *
* *
-* Retour : Nombre de caractères utilisés. *
+* Retour : Bilan de l'opération. *
* *
-* Remarques : - *
+* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après *
+* usage. *
* *
******************************************************************************/
-size_t g_imm_operand_to_string(const GImmOperand *operand, char value[IMM_MAX_SIZE])
+static bool g_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
{
- size_t result; /* Longueur à retourner */
+ bool result; /* Bilan à retourner */
+ const GImmediateOperand *operand; /* Version spécialisée */
ImmOperandDisplay display; /* Type d'affichage courant */
-
- display = g_imm_operand_get_display(operand);
-
- result = _g_imm_operand_to_string(operand, display, value);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
-* *
-* Description : Traduit un opérande en version humainement lisible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line)
-{
char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */
size_t len; /* Taille de l'élément inséré */
- len = g_imm_operand_to_string(operand, value);
-
- g_buffer_line_append_text(line, DLC_ASSEMBLY, value, len, RTT_IMMEDIATE, G_OBJECT(operand));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* pos = valeur résultante. [OUT] *
-* *
-* Description : Convertit une valeur immédiate en position de type phys_t. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_imm_operand_to_phys_t(const GImmOperand *operand, phys_t *pos)
-{
- bool result; /* Bilan à renvoyer */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_IMM_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = !MDS_IS_SIGNED(extra->size);
-
- if (result)
- *pos = operand->raw;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* addr = valeur résultante. [OUT] *
-* *
-* Description : Convertit une valeur immédiate en adresse de type virt_t. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_imm_operand_to_virt_t(const GImmOperand *operand, virt_t *addr)
-{
- bool result; /* Bilan à renvoyer */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_IMM_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = !MDS_IS_SIGNED(extra->size);
-
- if (result)
- *addr = operand->raw;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* val = valeur résultante. [OUT] *
-* *
-* Description : Convertit une valeur immédiate en valeur de type leb128_t. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_imm_operand_as_leb128(const GImmOperand *operand, leb128_t *val)
-{
- immop_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_IMM_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- *val = operand->raw;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à traiter. *
-* val = valeur résultante. [OUT] *
-* *
-* Description : Convertit une valeur immédiate en valeur de type uleb128_t. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_imm_operand_as_uleb128(const GImmOperand *operand, uleb128_t *val)
-{
- immop_extra_data_t *extra; /* Données insérées à consulter*/
-
- extra = GET_IMM_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- *val = operand->raw;
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
-* lock = précise le besoin en verrouillage. *
-* *
-* Description : Compare un opérande avec un autre. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int g_imm_operand_compare(const GImmOperand *a, const GImmOperand *b, bool lock)
-{
- int result; /* Bilan à retourner */
- immop_extra_data_t *ea; /* Données insérées à modifier */
- immop_extra_data_t *eb; /* Données insérées à modifier */
- GArchOperandClass *class; /* Classe parente normalisée */
-
- ea = GET_IMM_OP_EXTRA(a);
- eb = GET_IMM_OP_EXTRA(b);
-
- if (lock)
- {
- LOCK_GOBJECT_EXTRA(ea);
- LOCK_GOBJECT_EXTRA(eb);
- }
-
- result = sort_unsigned_long(ea->size, eb->size);
-
- if (result == 0)
- sort_uint64_t(a->raw, b->raw);
-
- if (result == 0)
- result = sort_unsigned_long(ea->def_display, eb->def_display);
-
- if (result == 0)
- result = sort_unsigned_long(ea->display, eb->display);
-
- if (result == 0)
- {
- class = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class);
- result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
- }
-
- if (lock)
- {
- UNLOCK_GOBJECT_EXTRA(eb);
- UNLOCK_GOBJECT_EXTRA(ea);
- }
-
- return result;
-
-}
-
-
-#ifdef INCLUDE_GTK_SUPPORT
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* binary = informations relatives au binaire chargé. *
-* *
-* Description : Construit un petit résumé concis de l'opérande. *
-* *
-* Retour : Chaîne de caractères à libérer après usage ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_imm_operand_build_tooltip(const GImmOperand *operand, const GLoadedBinary *binary)
-{
- char *result; /* Description à retourner */
- char value[IMM_MAX_SIZE]; /* Conversion artificielle */
- char *conv; /* Affichage de la Conversion */
-
- if (operand->raw <= UCHAR_MAX && isprint(operand->raw))
- switch (operand->raw)
- {
- case '&':
- asprintf(&result, _("Character: '&amp;'"));
- break;
- case '<':
- asprintf(&result, _("Character: '&lt;'"));
- break;
- case '>':
- asprintf(&result, _("Character: '&gt;'"));
- break;
- default:
- asprintf(&result, _("Character: '%c'"), (char)operand->raw);
- break;
- }
-
- else
- asprintf(&result, _("Character: &lt;not printable&gt;"));
-
- /* Binaire */
-
- _g_imm_operand_to_string(operand, IOD_BIN, value);
-
- asprintf(&conv, _("Binary: %s"), value);
-
- result = stradd(result, "\n");
- result = stradd(result, conv);
-
- free(conv);
-
- /* Octal */
-
- _g_imm_operand_to_string(operand, IOD_OCT, value);
-
- asprintf(&conv, _("Octal: %s"), value);
-
- result = stradd(result, "\n");
- result = stradd(result, conv);
-
- free(conv);
-
- /* Décimal */
-
- _g_imm_operand_to_string(operand, IOD_DEC, value);
-
- asprintf(&conv, _("Decimal: %s"), value);
-
- result = stradd(result, "\n");
- result = stradd(result, conv);
-
- free(conv);
-
- /* Hexadécimal */
-
- _g_imm_operand_to_string(operand, IOD_HEX, value);
-
- asprintf(&conv, _("Hexadecimal: %s"), value);
-
- result = stradd(result, "\n");
- result = stradd(result, conv);
-
- free(conv);
-
- return result;
-
-}
-
-
-#endif
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* lock = précise le besoin en verrouillage. *
-* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
-* *
-* Retour : Empreinte de l'élément représenté. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static guint g_imm_operand_hash(const GImmOperand *operand, bool lock)
-{
- guint result; /* Valeur à retourner */
- immop_extra_data_t *extra; /* Données insérées à modifier */
- GArchOperandClass *class; /* Classe parente normalisée */
-
- extra = GET_IMM_OP_EXTRA(operand);
-
- if (lock)
- LOCK_GOBJECT_EXTRA(extra);
-
- class = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class);
- result = class->hash(G_ARCH_OPERAND(operand), false);
-
- result ^= (operand->raw & 0xffffffff);
- result ^= (operand->raw >> 32);
-
- if (lock)
- UNLOCK_GOBJECT_EXTRA(extra);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_imm_operand_load(GImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- immop_extra_data_t *extra; /* Données insérées à modifier */
- uleb128_t value; /* Valeur ULEB128 à charger */
- uint8_t val; /* Champ de bits manipulé */
-
- parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class);
-
- result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
-
- if (result)
- {
- extra = GET_IMM_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = unpack_uleb128(&value, pbuf);
-
- if (result)
- extra->size = value;
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
-
- if (result)
- extra->def_display = val;
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
-
- if (result)
- extra->display = val;
-
- }
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- }
-
- if (result)
- result = extract_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_imm_operand_store(GImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- immop_extra_data_t *extra; /* Données insérées à modifier */
+ operand = G_IMMEDIATE_OPERAND(builder);
- parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class);
+ display = g_immediate_operand_get_display(operand);
- result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
+ len = _g_immediate_operand_to_string(operand, display, value);
- if (result)
- {
- extra = GET_IMM_OP_EXTRA(operand);
-
- LOCK_GOBJECT_EXTRA(extra);
-
- result = pack_uleb128((uleb128_t []){ extra->size }, pbuf);
-
- if (result)
- result = extend_packed_buffer(pbuf, (uint8_t []) { extra->def_display }, sizeof(uint8_t), false);
-
- if (result)
- result = extend_packed_buffer(pbuf, (uint8_t []) { extra->display }, sizeof(uint8_t), false);
-
- UNLOCK_GOBJECT_EXTRA(extra);
-
- }
+ result = (len > 0);
if (result)
- result = extend_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true);
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* COMMUNICATION D'UN CIBLAGE POTENTIEL */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = operande à consulter. *
-* src = localisation de l'instruction mère. *
-* format = format reconnu pour le binaire chargé. *
-* proc = architecture associée à ce même binaire. *
-* addr = localisation de la cible. [OUT] *
-* *
-* Description : Obtient l'adresse de la cible visée par un opérande. *
-* *
-* Retour : true si la cible est valide, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_imm_operand_get_addr(const GImmOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr)
-{
- bool result; /* Bilan à retourner */
- virt_t virt; /* Adresse virtuelle */
-
- result = g_imm_operand_to_virt_t(operand, &virt);
-
- if (result)
- result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, addr);
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONSTRUCTION D'UN CONTENU ALTERNATIF */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = operande à consulter. *
-* text = texte alternatif de représentation. *
-* *
-* Description : Construit un opérande de représentation alternative. *
-* *
-* Retour : Nouvel opérande, en version renommée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GRenamedOperand *g_imm_operand_build(const GImmOperand *operand, const char *text)
-{
- GRenamedOperand *result; /* Instance à retourner */
-
- result = G_RENAMED_OPERAND(g_known_imm_operand_new(operand, text));
+ add_to_sized_binary(out, value, len);
return result;
diff --git a/src/arch/operands/immediate.h b/src/arch/operands/immediate.h
index 7c1ff03..d66349a 100644
--- a/src/arch/operands/immediate.h
+++ b/src/arch/operands/immediate.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* immediate.h - prototypes pour les opérandes représentant des valeurs numériques
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,17 +25,22 @@
#define _ARCH_OPERANDS_IMMEDIATE_H
-#include <glib-object.h>
#include <stdbool.h>
#include <stdint.h>
-#include "../archbase.h"
#include "../operand.h"
#include "../../analysis/content.h"
+#include "../../common/datatypes.h"
+#include "../../glibext/helpers.h"
+#define G_TYPE_IMMEDIATE_OPERAND (g_immediate_operand_get_type())
+
+DECLARE_GTYPE(GImmediateOperand, g_immediate_operand, G, IMMEDIATE_OPERAND);
+
+
/* Etats particuliers d'un opérande de valeur immédiate */
typedef enum _ImmOpFlag
{
@@ -57,86 +62,39 @@ typedef enum _ImmOperandDisplay
} ImmOperandDisplay;
-#define IOD_LAST_VALID IOD_CHAR
-
-
-#define G_TYPE_IMM_OPERAND g_imm_operand_get_type()
-#define G_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_IMM_OPERAND, GImmOperand))
-#define G_IS_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_IMM_OPERAND))
-#define G_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_IMM_OPERAND, GImmOperandClass))
-#define G_IS_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_IMM_OPERAND))
-#define G_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_IMM_OPERAND, GImmOperandClass))
-
-
-/* Définition d'un opérande de valeur numérique (instance) */
-typedef struct _GImmOperand GImmOperand;
-
-/* Définition d'un opérande de valeur numérique (classe) */
-typedef struct _GImmOperandClass GImmOperandClass;
-
-
-/* Indique le type défini pour un opérande d'architecture. */
-GType g_imm_operand_get_type(void);
/* Crée un opérande réprésentant une valeur numérique. */
-GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian);
-
-#define g_imm_operand_new_from_data(size, content, addr, endian) \
- _g_imm_operand_new_from_data(size, content, addr, NULL, endian)
+GArchOperand *g_immediate_operand_new_from_value(MemoryDataSize, uint64_t);
/* Crée un opérande réprésentant une valeur numérique. */
-GArchOperand *g_imm_operand_new_from_value(MemoryDataSize, uint64_t);
+GArchOperand *g_immediate_operand_new_from_data(MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian);
/* Renseigne la taille de la valeur indiquée à la construction. */
-MemoryDataSize g_imm_operand_get_size(const GImmOperand *);
+MemoryDataSize g_immediate_operand_get_size(const GImmediateOperand *);
/* Fournit la valeur portée par une opérande numérique. */
-bool g_imm_operand_get_value(const GImmOperand *, MemoryDataSize, ...);
+bool g_immediate_operand_get_value(const GImmediateOperand *, MemoryDataSize, ...);
+
+/* Définit la nouvelle valeur de l'opérande à une valeur. */
+void g_immediate_operand_set_value(GImmediateOperand *, MemoryDataSize, uint64_t);
/* Fournit la valeur brute représentée par l'opérande. */
-uint64_t g_imm_operand_get_raw_value(const GImmOperand *);
+uint64_t g_immediate_operand_get_raw_value(const GImmediateOperand *);
-/* Définit la nouvelle valeur de l'opérande à une valeur. */
-void g_imm_operand_set_value(GImmOperand *, MemoryDataSize, uint64_t);
+/* Indique le signe d'une valeur immédiate. */
+bool g_immediate_operand_is_negative(const GImmediateOperand *);
/* Définit le format textuel par défaut de la valeur. */
-void g_imm_operand_set_default_display(GImmOperand *, ImmOperandDisplay);
+void g_immediate_operand_set_default_display(GImmediateOperand *, ImmOperandDisplay);
/* Indique le format textuel par défaut de la valeur. */
-ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *);
+ImmOperandDisplay g_immediate_operand_get_default_display(const GImmediateOperand *);
/* Définit la grande ligne du format textuel de la valeur. */
-void g_imm_operand_set_display(GImmOperand *, ImmOperandDisplay);
+void g_immediate_operand_set_display(GImmediateOperand *, ImmOperandDisplay);
/* Indique la grande ligne du format textuel de la valeur. */
-ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *);
-
-/* Indique le signe d'une valeur immédiate. */
-bool g_imm_operand_is_negative(const GImmOperand *);
-
-/* Indique si une valeur immédiate est nulle ou non. */
-bool g_imm_operand_is_null(const GImmOperand *);
-
-/**
- * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE,
- * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire.
- */
-#define IMM_MAX_SIZE 66
-
-/* Construit la chaîne de caractères correspondant à l'opérande. */
-size_t g_imm_operand_to_string(const GImmOperand *, char [IMM_MAX_SIZE]);
-
-/* Convertit une valeur immédiate en position de type phys_t. */
-bool g_imm_operand_to_phys_t(const GImmOperand *, phys_t *);
-
-/* Convertit une valeur immédiate en adresse de type virt_t. */
-bool g_imm_operand_to_virt_t(const GImmOperand *, virt_t *);
-
-/* Convertit une valeur immédiate en valeur de type leb128_t. */
-void g_imm_operand_as_leb128(const GImmOperand *, leb128_t *);
-
-/* Convertit une valeur immédiate en valeur de type uleb128_t. */
-void g_imm_operand_as_uleb128(const GImmOperand *, uleb128_t *);
+ImmOperandDisplay g_immediate_operand_get_display(const GImmediateOperand *);
diff --git a/src/arch/operands/known-int.h b/src/arch/operands/known-int.h
new file mode 100644
index 0000000..021fbf2
--- /dev/null
+++ b/src/arch/operands/known-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * known-int.h - définitions internes pour les opérandes représentant des valeurs numériques avec sémantique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_KNOWN_INT_H
+#define _ARCH_OPERANDS_KNOWN_INT_H
+
+
+#include "immediate-int.h"
+#include "known.h"
+
+
+
+/* Définition d'un remplacement d'opérande de valeur numérique (instance) */
+struct _GKnownImmediateOperand
+{
+ GImmediateOperand parent; /* Instance parente */
+
+ char *alt_text; /* Alternative humaine */
+
+};
+
+/* Définition d'un remplacement d'opérande de valeur numérique (classe) */
+struct _GKnownImmediateOperandClass
+{
+ GImmediateOperandClass parent; /* Classe parente */
+
+};
+
+
+/* Met en place un opérande remplaçant visuellement une valeur. */
+bool g_known_immediate_operand_create(GKnownImmediateOperand *, const GImmediateOperand *, const char *);
+
+
+
+#endif /* _ARCH_OPERANDS_KNOWN_INT_H */
diff --git a/src/arch/operands/known-ui.c b/src/arch/operands/known-ui.c
new file mode 100644
index 0000000..9b7507a
--- /dev/null
+++ b/src/arch/operands/known-ui.c
@@ -0,0 +1,79 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * known-ui.c - opérandes représentant des valeurs numériques avec sémantique sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "known-ui.h"
+
+
+#include "known-int.h"
+#include "../../common/cpp.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Traduit un opérande en version humainement lisible. */
+static void g_known_immediate_operand_ui_print(const GArchOperandUI *, GBufferLine *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'opérande UI. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_known_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface)
+{
+ iface->print = g_known_immediate_operand_ui_print;
+ iface->build_tooltip = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_known_immediate_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line)
+{
+ GKnownImmediateOperand *known; /* Version de base */
+
+ known = G_KNOWN_IMMEDIATE_OPERAND(operand);
+
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_IMMEDIATE, SL(known->alt_text), NULL, G_OBJECT(operand));
+
+}
diff --git a/src/arch/operands/known-ui.h b/src/arch/operands/known-ui.h
new file mode 100644
index 0000000..fa2dc62
--- /dev/null
+++ b/src/arch/operands/known-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * known-ui.h - prototypes pour les opérandes représentant des valeurs numériques avec sémantique sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_KNOWN_UI_H
+#define _ARCH_OPERANDS_KNOWN_UI_H
+
+
+#include "../operand-ui-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface d'opérande UI. */
+void g_known_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_KNOWN_UI_H */
diff --git a/src/arch/operands/known.c b/src/arch/operands/known.c
index 5402879..c9e177f 100644
--- a/src/arch/operands/known.c
+++ b/src/arch/operands/known.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* known.c - opérandes représentant des valeurs numériques avec sémantique
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,81 +24,80 @@
#include "known.h"
-#include <assert.h>
#include <malloc.h>
#include <string.h>
-#include "immediate-int.h"
-#include "rename-int.h"
-#include "../../analysis/db/misc/rlestr.h"
-#include "../../core/columns.h"
-#include "../../core/logs.h"
+#include "known-int.h"
+#include "../../common/cpp.h"
+#include "../../glibext/comparable-int.h"
+#include "../../glibext/hashable-int.h"
+#include "../../glibext/serialize-int.h"
+#include "../../glibext/strbuilder-int.h"
/* ----------------------- REMPLACEMENT DE VALEURS IMMEDIATES ----------------------- */
-/* Définition d'un remplacement d'opérande de valeur numérique (instance) */
-struct _GKnownImmOperand
-{
- GImmOperand parent; /* Instance parente */
+/* Initialise la classe des remplacements d'opérandes. */
+static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *);
- char *alt_text; /* Alternative humaine */
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *);
-};
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *);
-/* Définition d'un remplacement d'opérande de valeur numérique (classe) */
-struct _GKnownImmOperandClass
-{
- GImmOperandClass parent; /* Classe parente */
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_known_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *);
-};
-
-
-/* Initialise la classe des remplacements d'opérandes. */
-static void g_known_imm_operand_class_init(GKnownImmOperandClass *);
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *);
/* Initialise un remplacement d'opérande de valeur immédiate. */
-static void g_known_imm_operand_init(GKnownImmOperand *);
-
-/* Procède à l'initialisation de l'interface de renommage. */
-static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface *);
+static void g_known_immediate_operand_init(GKnownImmediateOperand *);
/* Supprime toutes les références externes. */
-static void g_known_imm_operand_dispose(GKnownImmOperand *);
+static void g_known_immediate_operand_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_known_imm_operand_finalize(GKnownImmOperand *);
+static void g_known_immediate_operand_finalize(GObject *);
+
+
+/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Réalise une comparaison étendue entre objets. */
+static int g_known_immediate_operand_compare(const GComparableObject *, const GComparableObject *);
-/* Compare un opérande avec un autre. */
-static int g_known_imm_operand_compare(const GKnownImmOperand *, const GKnownImmOperand *, bool);
-/* Traduit un opérande en version humainement lisible. */
-static void g_known_imm_operand_print(const GKnownImmOperand *, GBufferLine *);
+/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint g_known_imm_operand_hash(const GKnownImmOperand *, bool);
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_known_imm_operand_load(GKnownImmOperand *, GObjectStorage *, packed_buffer_t *);
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+static guint g_known_immediate_operand_hash(const GHashableObject *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_known_imm_operand_store(GKnownImmOperand *, GObjectStorage *, packed_buffer_t *);
+/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
-/* ------------------------- AFFICHAGE D'UN CONTENU RENOMME ------------------------- */
+/* Charge un objet depuis un flux de données. */
+static bool g_known_immediate_operand_load(GSerializableObject *, GObjectStorage *, int);
-/* Fournit un texte comme représentation alternative d'opérande. */
-static const char *g_known_imm_operand_get_text(const GKnownImmOperand *);
+/* Sauvegarde un objet dans un flux de données. */
+static bool g_known_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int);
+
+
+
+/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+static bool g_known_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
@@ -108,8 +107,12 @@ static const char *g_known_imm_operand_get_text(const GKnownImmOperand *);
/* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */
-G_DEFINE_TYPE_WITH_CODE(GKnownImmOperand, g_known_imm_operand, G_TYPE_IMM_OPERAND,
- G_IMPLEMENT_INTERFACE(G_TYPE_RENAMED_OPERAND, g_known_imm_operand_renamed_interface_init));
+G_DEFINE_TYPE_WITH_CODE(GKnownImmediateOperand, g_known_immediate_operand, G_TYPE_IMMEDIATE_OPERAND,
+ G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_known_immediate_operand_comparable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_known_immediate_operand_hashable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_immediate_operand_serializable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_known_immediate_operand_string_builder_iface_init)
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_known_immediate_operand_ui_arch_operand_ui_iface_init));
/******************************************************************************
@@ -124,33 +127,42 @@ G_DEFINE_TYPE_WITH_CODE(GKnownImmOperand, g_known_imm_operand, G_TYPE_IMM_OPERAN
* *
******************************************************************************/
-static void g_known_imm_operand_class_init(GKnownImmOperandClass *klass)
+static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_known_imm_operand_dispose;
- object->finalize = (GObjectFinalizeFunc)g_known_imm_operand_finalize;
+ object->dispose = g_known_immediate_operand_dispose;
+ object->finalize = g_known_immediate_operand_finalize;
+
+}
- operand->compare = (operand_compare_fc)g_known_imm_operand_compare;
- operand->print = (operand_print_fc)g_known_imm_operand_print;
- operand->hash = (operand_hash_fc)g_known_imm_operand_hash;
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- operand->load = (load_operand_fc)g_known_imm_operand_load;
- operand->store = (store_operand_fc)g_known_imm_operand_store;
+static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface)
+{
+ iface->compare = g_known_immediate_operand_compare;
}
/******************************************************************************
* *
-* Paramètres : operand = instance à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Initialise un remplacement d'opérande de valeur immédiate. *
+* Description : Procède à l'initialisation de l'interface de détermination. *
* *
* Retour : - *
* *
@@ -158,9 +170,9 @@ static void g_known_imm_operand_class_init(GKnownImmOperandClass *klass)
* *
******************************************************************************/
-static void g_known_imm_operand_init(GKnownImmOperand *operand)
+static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface)
{
- operand->alt_text = NULL;
+ iface->hash = g_known_immediate_operand_hash;
}
@@ -169,7 +181,7 @@ static void g_known_imm_operand_init(GKnownImmOperand *operand)
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Procède à l'initialisation de l'interface de renommage. *
+* Description : Procède à l'initialisation de l'interface de sérialisation. *
* *
* Retour : - *
* *
@@ -177,18 +189,19 @@ static void g_known_imm_operand_init(GKnownImmOperand *operand)
* *
******************************************************************************/
-static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface *iface)
+static void g_known_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *iface)
{
- iface->get_text = (get_renamed_text_fc)g_known_imm_operand_get_text;
+ iface->load = g_known_immediate_operand_load;
+ iface->store = g_known_immediate_operand_store;
}
/******************************************************************************
* *
-* Paramètres : operand = instance d'objet GLib à traiter. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Supprime toutes les références externes. *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
* *
* Retour : - *
* *
@@ -196,12 +209,28 @@ static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface
* *
******************************************************************************/
-static void g_known_imm_operand_dispose(GKnownImmOperand *operand)
+static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface)
{
- if (operand->alt_text != NULL)
- free(operand->alt_text);
+ iface->to_string = g_known_immediate_operand_to_string;
- G_OBJECT_CLASS(g_known_imm_operand_parent_class)->dispose(G_OBJECT(operand));
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise un remplacement d'opérande de valeur immédiate. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_known_immediate_operand_init(GKnownImmediateOperand *operand)
+{
+ operand->alt_text = NULL;
}
@@ -210,7 +239,7 @@ static void g_known_imm_operand_dispose(GKnownImmOperand *operand)
* *
* Paramètres : operand = instance d'objet GLib à traiter. *
* *
-* Description : Procède à la libération totale de la mémoire. *
+* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
@@ -218,180 +247,199 @@ static void g_known_imm_operand_dispose(GKnownImmOperand *operand)
* *
******************************************************************************/
-static void g_known_imm_operand_finalize(GKnownImmOperand *operand)
+static void g_known_immediate_operand_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_known_imm_operand_parent_class)->finalize(G_OBJECT(operand));
+ G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : old = opérande à venir copier avant son remplacement. *
-* alt = texte alternatif à présenter pour l'impression. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
-* Description : Crée un opérande remplaçant visuellement une valeur. *
+* Description : Procède à la libération totale de la mémoire. *
* *
-* Retour : Instruction mise en place. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_known_imm_operand_new(const GImmOperand *old, const char *alt)
+static void g_known_immediate_operand_finalize(GObject *object)
{
- GKnownImmOperand *result; /* Remplacement à retourner */
- immop_extra_data_t *src; /* Données insérées à consulter*/
- immop_extra_data_t *dest; /* Données insérées à modifier */
+ GKnownImmediateOperand *operand; /* Version spécialisée */
- result = g_object_new(G_TYPE_KNOWN_IMM_OPERAND, NULL);
+ operand = G_KNOWN_IMMEDIATE_OPERAND(object);
- result->parent.raw = old->raw;
+ if (operand->alt_text != NULL)
+ free(operand->alt_text);
- src = GET_IMM_OP_EXTRA(old);
- dest = GET_IMM_OP_EXTRA(&result->parent);
+ G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->finalize(object);
- LOCK_GOBJECT_EXTRA(src);
+}
- *(&dest->parent) = *(&src->parent);
- dest->size = src->size;
+/******************************************************************************
+* *
+* Paramètres : old = opérande à venir copier avant son remplacement. *
+* alt = texte alternatif à présenter pour l'impression. *
+* *
+* Description : Crée un opérande remplaçant visuellement une valeur. *
+* *
+* Retour : Instruction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- dest->def_display = src->def_display;
- dest->display = src->display;
+GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *old, const char *alt)
+{
+ GKnownImmediateOperand *result; /* Remplacement à retourner */
- UNLOCK_GOBJECT_EXTRA(src);
+ result = g_object_new(G_TYPE_KNOWN_IMMEDIATE_OPERAND, NULL);
- result->alt_text = strdup(alt);
+ if (!g_known_immediate_operand_create(result, old, alt))
+ g_clear_object(&result);
return G_ARCH_OPERAND(result);
}
-
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
-* lock = précise le besoin en verrouillage. *
+* Paramètres : operand = instance à initialiser pleinement. *
+* old = opérande à venir copier avant son remplacement. *
+* alt = texte alternatif à présenter pour l'impression. *
* *
-* Description : Compare un opérande avec un autre. *
+* Description : Met en place un opérande remplaçant visuellement une valeur. *
* *
-* Retour : Bilan de la comparaison. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static int g_known_imm_operand_compare(const GKnownImmOperand *a, const GKnownImmOperand *b, bool lock)
+bool g_known_immediate_operand_create(GKnownImmediateOperand *operand, const GImmediateOperand *old, const char *alt)
{
- int result; /* Bilan à retourner */
- immop_extra_data_t *ea; /* Données insérées à consulter*/
- immop_extra_data_t *eb; /* Données insérées à consulter*/
- GArchOperandClass *class; /* Classe parente normalisée */
+ bool result; /* Bilan à retourner */
+ immop_extra_data_t extra; /* Données insérées à consulter*/
- ea = GET_IMM_OP_EXTRA(G_IMM_OPERAND(a));
- eb = GET_IMM_OP_EXTRA(G_IMM_OPERAND(b));
+ result = true;
- if (lock)
- {
- LOCK_GOBJECT_EXTRA(ea);
- LOCK_GOBJECT_EXTRA(eb);
- }
+ extra = GET_IMM_OP_EXTRA(old);
- result = strcmp(a->alt_text, b->alt_text);
+ SET_IMM_OP_EXTRA(operand, &extra);
- if (result == 0)
- {
- class = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class);
- result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
- }
+ G_IMMEDIATE_OPERAND(operand)->raw = G_IMMEDIATE_OPERAND(old)->raw;
- if (lock)
- {
- UNLOCK_GOBJECT_EXTRA(eb);
- UNLOCK_GOBJECT_EXTRA(ea);
- }
+ operand->alt_text = strdup(alt);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* COMPARAISON DETAILLEE DE DEUX OBJETS */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
* *
-* Description : Traduit un opérande en version humainement lisible. *
+* Description : Réalise une comparaison étendue entre objets. *
* *
-* Retour : - *
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_known_imm_operand_print(const GKnownImmOperand *operand, GBufferLine *line)
+static int g_known_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other)
{
- size_t len; /* Taille de l'élément inséré */
+ int result; /* Bilan à retourner */
+ GComparableObjectInterface *iface; /* Interface utilisée */
+ GComparableObjectInterface *parent_iface; /* Interface parente */
+ GKnownImmediateOperand *operand_a; /* Version spécialisée #0 */
+ GKnownImmediateOperand *operand_b; /* Version spécialisée #1 */
+
+ iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
- len = strlen(operand->alt_text);
+ parent_iface = g_type_interface_peek_parent(iface);
- g_buffer_line_append_text(line, DLC_ASSEMBLY, operand->alt_text, len, RTT_IMMEDIATE, G_OBJECT(operand));
+ result = parent_iface->compare(object, other);
+
+ if (result == 0)
+ {
+ operand_a = G_KNOWN_IMMEDIATE_OPERAND(object);
+ operand_b = G_KNOWN_IMMEDIATE_OPERAND(other);
+
+ result = strcmp(operand_a->alt_text, operand_b->alt_text);
+
+ }
+
+ return result;
}
+/* ---------------------------------------------------------------------------------- */
+/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* lock = précise le besoin en verrouillage. *
+* Paramètres : object = objet dont l'instance est à consulter. *
* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* Description : Calcule l'empreinte sur 32 bits d'un objet. *
* *
-* Retour : Empreinte de l'élément représenté. *
+* Retour : Valeur de représentation, unique pour l'objet ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-static guint g_known_imm_operand_hash(const GKnownImmOperand *operand, bool lock)
+static guint g_known_immediate_operand_hash(const GHashableObject *object)
{
guint result; /* Valeur à retourner */
- immop_extra_data_t *extra; /* Données insérées à consulter*/
- GArchOperandClass *class; /* Classe parente normalisée */
+ GHashableObjectInterface *iface; /* Interface utilisée */
+ GHashableObjectInterface *parent_iface; /* Interface parente */
+ GKnownImmediateOperand *operand; /* Version spécialisée */
- extra = GET_IMM_OP_EXTRA(G_IMM_OPERAND(operand));
+ iface = G_HASHABLE_OBJECT_GET_IFACE(object);
- if (lock)
- LOCK_GOBJECT_EXTRA(extra);
+ parent_iface = g_type_interface_peek_parent(iface);
- class = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class);
- result = class->hash(G_ARCH_OPERAND(operand), false);
+ result = parent_iface->hash(object);
- result ^= g_str_hash(operand->alt_text);
+ operand = G_KNOWN_IMMEDIATE_OPERAND(object);
- if (lock)
- UNLOCK_GOBJECT_EXTRA(extra);
+ result ^= g_str_hash(operand->alt_text);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE CONSERVATION ET RESTAURATION */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Charge un objet depuis un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -399,30 +447,31 @@ static guint g_known_imm_operand_hash(const GKnownImmOperand *operand, bool lock
* *
******************************************************************************/
-static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_known_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- rle_string str; /* Chaîne à charger */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *parent_iface; /* Interface parente */
+ sized_binary_t str; /* Texte alternatif rechargé */
+ GKnownImmediateOperand *operand; /* Version spécialisée */
+
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
- parent = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class);
+ parent_iface = g_type_interface_peek_parent(iface);
- result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = parent_iface->load(object, storage, fd);
if (result)
{
- setup_empty_rle_string(&str);
+ init_sized_binary(&str);
- result = unpack_rle_string(&str, pbuf);
+ load_sized_binary_as_string(&str, fd);
- if (result)
- {
- if (get_rle_string(&str) != NULL)
- operand->alt_text = strdup(get_rle_string(&str));
+ operand = G_KNOWN_IMMEDIATE_OPERAND(object);
- exit_rle_string(&str);
+ operand->alt_text = strdup(str.static_data);
- }
+ exit_sized_binary(&str);
}
@@ -433,11 +482,11 @@ static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage *
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Sauvegarde un objet dans un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -445,54 +494,64 @@ static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage *
* *
******************************************************************************/
-static bool g_known_imm_operand_store(GKnownImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_known_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- rle_string str; /* Chaîne à conserver */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *parent_iface; /* Interface parente */
+ GKnownImmediateOperand *operand; /* Version spécialisée */
+ sized_binary_t str; /* Texte alternatif à conserver*/
- parent = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class);
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
- result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
+ parent_iface = g_type_interface_peek_parent(iface);
- if (result)
- {
- init_static_rle_string(&str, operand->alt_text);
+ result = parent_iface->store(object, storage, fd);
+ if (!result) goto exit;
- result = pack_rle_string(&str, pbuf);
+ operand = G_KNOWN_IMMEDIATE_OPERAND(object);
- exit_rle_string(&str);
+ setup_sized_binary_from_static_string(&str, operand->alt_text);
- }
+ result = store_sized_binary_as_string(&str, fd);
+
+ exit:
return result;
}
-
/* ---------------------------------------------------------------------------------- */
-/* AFFICHAGE D'UN CONTENU RENOMME */
+/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : operand = operande à consulter. *
+* Paramètres : builder = objet dont l'instance est exportable. *
+* flags = éventuelles indications pour l'opération. *
+* out = chaîne de caractères mise en place. [OUT] *
* *
-* Description : Fournit un texte comme représentation alternative d'opérande.*
+* Description : Exporte une chaîne de caractères à partir d'un objet. *
* *
-* Retour : Chaîne de caractère de représentation alternative. *
+* Retour : Bilan de l'opération. *
* *
-* Remarques : - *
+* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après *
+* usage. *
* *
******************************************************************************/
-static const char *g_known_imm_operand_get_text(const GKnownImmOperand *operand)
+static bool g_known_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
{
- const char *result; /* Texte à retourner */
+ bool result; /* Bilan à retourner */
+ const GKnownImmediateOperand *operand; /* Version spécialisée */
+
+ result = true;
+
+ operand = G_KNOWN_IMMEDIATE_OPERAND(builder);
- result = operand->alt_text;
+ add_to_sized_binary(out, operand->alt_text, strlen(operand->alt_text));
return result;
diff --git a/src/arch/operands/known.h b/src/arch/operands/known.h
index eb84d3b..a8b563f 100644
--- a/src/arch/operands/known.h
+++ b/src/arch/operands/known.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* known.h - prototypes pour les opérandes représentant des valeurs numériques avec sémantique
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,34 +25,18 @@
#define _ARCH_OPERANDS_KNOWN_H
-#include <glib-object.h>
-
-
#include "immediate.h"
-#include "../operand.h"
-
-
-
-#define G_TYPE_KNOWN_IMM_OPERAND g_known_imm_operand_get_type()
-#define G_KNOWN_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperand))
-#define G_IS_KNOWN_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KNOWN_IMM_OPERAND))
-#define G_KNOWN_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperandClass))
-#define G_IS_KNOWN_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KNOWN_IMM_OPERAND))
-#define G_KNOWN_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperandClass))
+#include "../../glibext/helpers.h"
-/* Définition d'un remplacement d'opérande de valeur numérique (instance) */
-typedef struct _GKnownImmOperand GKnownImmOperand;
-/* Définition d'un remplacement d'opérande de valeur numérique (classe) */
-typedef struct _GKnownImmOperandClass GKnownImmOperandClass;
+#define G_TYPE_KNOWN_IMMEDIATE_OPERAND (g_known_immediate_operand_get_type())
+DECLARE_GTYPE(GKnownImmediateOperand, g_known_immediate_operand, G, KNOWN_IMMEDIATE_OPERAND);
-/* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */
-GType g_known_imm_operand_get_type(void);
/* Crée un opérande remplaçant visuellement une valeur. */
-GArchOperand *g_known_imm_operand_new(const GImmOperand *, const char *);
+GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *, const char *);
diff --git a/src/arch/operands/register-int.h b/src/arch/operands/register-int.h
index a887567..93cf025 100644
--- a/src/arch/operands/register-int.h
+++ b/src/arch/operands/register-int.h
@@ -26,8 +26,6 @@
#include "register.h"
-
-
#include "../operand-int.h"
@@ -49,5 +47,9 @@ struct _GRegisterOperandClass
};
+/* Met en place un opérande réprésentant une valeur numérique. */
+bool g_register_operand_create(GRegisterOperand *, GArchRegister *);
+
+
#endif /* _ARCH_OPERANDS_REGISTER_INT_H */
diff --git a/src/arch/operands/register-ui.c b/src/arch/operands/register-ui.c
new file mode 100644
index 0000000..513a24f
--- /dev/null
+++ b/src/arch/operands/register-ui.c
@@ -0,0 +1,93 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * register-ui.c - opérandes représentant des registres sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "register-ui.h"
+
+
+#include "register.h"
+#include "../../glibext/strbuilder.h"
+#include "../../glibext/options/asm.h"
+
+
+
+/* Traduit un opérande en version humainement lisible. */
+static void g_register_operand_ui_print(const GArchOperandUI *, GBufferLine *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'opérande UI. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_register_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface)
+{
+ iface->print = g_register_operand_ui_print;
+ iface->build_tooltip = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_register_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line)
+{
+ GStringBuilder *builder; /* Autre version de l'opérande */
+ sized_binary_t str; /* Chaîne équivalente produite */
+ bool status; /* Bilan d'une conversion */
+
+ builder = G_STRING_BUILDER(operand);
+
+ init_sized_binary(&str);
+
+ status = g_string_builder_to_string(builder, 0 /* flags */, &str);
+
+ if (status)
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_REGISTER,
+ str.static_data, str.size, NULL, G_OBJECT(operand));
+
+ else
+ g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_REGISTER,
+ "??", 2, NULL, G_OBJECT(operand));
+
+ exit_sized_binary(&str);
+
+}
diff --git a/src/arch/operands/register-ui.h b/src/arch/operands/register-ui.h
new file mode 100644
index 0000000..16be67b
--- /dev/null
+++ b/src/arch/operands/register-ui.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * register-ui.h - prototypes pour les opérandes représentant des registres sous forme graphique
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_OPERANDS_REGISTER_UI_H
+#define _ARCH_OPERANDS_REGISTER_UI_H
+
+
+#include "../operand-ui-int.h" // FIXME ??
+
+
+
+/* Procède à l'initialisation de l'interface d'opérande UI. */
+void g_register_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *);
+
+
+
+#endif /* _ARCH_OPERANDS_REGISTER_UI_H */
diff --git a/src/arch/operands/register.c b/src/arch/operands/register.c
index 4615a99..cad2c4e 100644
--- a/src/arch/operands/register.c
+++ b/src/arch/operands/register.c
@@ -28,7 +28,10 @@
#include "register-int.h"
-#include "../storage.h"
+#include "../../glibext/comparable-int.h"
+#include "../../glibext/hashable-int.h"
+#include "../../glibext/serialize-int.h"
+#include "../../glibext/strbuilder-int.h"
@@ -38,34 +41,61 @@
/* Initialise la classe des opérandes de registre. */
static void g_register_operand_class_init(GRegisterOperandClass *);
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_register_operand_serializable_object_iface_init(GSerializableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *);
+
/* Initialise une instance d'opérande de registre. */
static void g_register_operand_init(GRegisterOperand *);
/* Supprime toutes les références externes. */
-static void g_register_operand_dispose(GRegisterOperand *);
+static void g_register_operand_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_register_operand_finalize(GRegisterOperand *);
+static void g_register_operand_finalize(GObject *);
+
+
+
+/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */
+
+
+/* Réalise une comparaison étendue entre objets. */
+static int g_register_operand_compare(const GComparableObject *, const GComparableObject *);
+
+/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+static guint g_register_operand_hash(const GHashableObject *);
-/* Compare un opérande avec un autre. */
-static int g_register_operand_compare(const GRegisterOperand *, const GRegisterOperand *, bool);
-/* Traduit un opérande en version humainement lisible. */
-static void g_register_operand_print(const GRegisterOperand *, GBufferLine *);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint g_register_operand_hash(const GRegisterOperand *, bool);
+/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_register_operand_load(GRegisterOperand *, GObjectStorage *, packed_buffer_t *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_register_operand_store(GRegisterOperand *, GObjectStorage *, packed_buffer_t *);
+/* Charge un objet depuis un flux de données. */
+static bool g_register_operand_load(GSerializableObject *, GObjectStorage *, int);
+
+/* Sauvegarde un objet dans un flux de données. */
+static bool g_register_operand_store(const GSerializableObject *, GObjectStorage *, int);
+
+
+
+/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+static bool g_register_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
@@ -75,7 +105,12 @@ static bool g_register_operand_store(GRegisterOperand *, GObjectStorage *, packe
/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */
-G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE_WITH_CODE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND,
+ G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_register_operand_comparable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_register_operand_hashable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_register_operand_serializable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_register_operand_string_builder_iface_init)
+ G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_register_operand_ui_arch_operand_ui_iface_init));
/******************************************************************************
@@ -93,23 +128,88 @@ G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND);
static void g_register_operand_class_init(GRegisterOperandClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_register_operand_dispose;
- object->finalize = (GObjectFinalizeFunc)g_register_operand_finalize;
+ object->dispose = g_register_operand_dispose;
+ object->finalize = g_register_operand_finalize;
- operand = G_ARCH_OPERAND_CLASS(klass);
+}
- operand->compare = (operand_compare_fc)g_register_operand_compare;
- operand->print = (operand_print_fc)g_register_operand_print;
- operand->hash = (operand_hash_fc)g_register_operand_hash;
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- operand->load = (load_operand_fc)g_register_operand_load;
- operand->store = (store_operand_fc)g_register_operand_store;
+static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *iface)
+{
+ iface->compare = g_register_operand_compare;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de détermination. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *iface)
+{
+ iface->hash = g_register_operand_hash;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de sérialisation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_register_operand_serializable_object_iface_init(GSerializableObjectInterface *iface)
+{
+ iface->load = g_register_operand_load;
+ iface->store = g_register_operand_store;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *iface)
+{
+ iface->to_string = g_register_operand_to_string;
}
@@ -135,7 +235,7 @@ static void g_register_operand_init(GRegisterOperand *operand)
/******************************************************************************
* *
-* Paramètres : binary = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -145,18 +245,22 @@ static void g_register_operand_init(GRegisterOperand *operand)
* *
******************************************************************************/
-static void g_register_operand_dispose(GRegisterOperand *operand)
+static void g_register_operand_dispose(GObject *object)
{
+ GRegisterOperand *operand; /* Version spécialisée */
+
+ operand = G_REGISTER_OPERAND(object);
+
g_clear_object(&operand->reg);
- G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(G_OBJECT(operand));
+ G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : binary = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -166,9 +270,36 @@ static void g_register_operand_dispose(GRegisterOperand *operand)
* *
******************************************************************************/
-static void g_register_operand_finalize(GRegisterOperand *operand)
+static void g_register_operand_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser pleinement. *
+* reg = registre matériel à représenter. *
+* *
+* Description : Met en place un opérande réprésentant une valeur numérique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_register_operand_create(GRegisterOperand *operand, GArchRegister *reg)
{
- G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(G_OBJECT(operand));
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ operand->reg = reg;
+ ref_object(reg);
+
+ return result;
}
@@ -190,8 +321,7 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand)
GArchRegister *result; /* Instance à retourner */
result = operand->reg;
-
- g_object_ref(G_OBJECT(result));
+ ref_object(result);
return result;
@@ -200,17 +330,16 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand)
/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* COMPARAISON DETAILLEE DE DEUX OBJETS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
-* lock = précise le besoin en verrouillage. *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
* *
-* Description : Compare un opérande avec un autre. *
+* Description : Réalise une comparaison étendue entre objets. *
* *
* Retour : Bilan de la comparaison. *
* *
@@ -218,17 +347,25 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand)
* *
******************************************************************************/
-static int g_register_operand_compare(const GRegisterOperand *a, const GRegisterOperand *b, bool lock)
+static int g_register_operand_compare(const GComparableObject *object, const GComparableObject *other)
{
int result; /* Bilan à retourner */
- GArchOperandClass *class; /* Classe parente normalisée */
+ GComparableObjectInterface *iface; /* Interface utilisée */
+ GComparableObjectInterface *parent_iface; /* Interface parente */
+ GRegisterOperand *operand; /* Version spécialisée */
+
+ iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
- result = g_arch_register_compare(a->reg, b->reg);
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ result = parent_iface->compare(object, other);
if (result == 0)
{
- class = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class);
- result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ operand = G_REGISTER_OPERAND(object);
+
+ result = g_comparable_object_compare(G_COMPARABLE_OBJECT(operand->reg), other);
+
}
return result;
@@ -236,53 +373,96 @@ static int g_register_operand_compare(const GRegisterOperand *a, const GRegister
}
+
+/* ---------------------------------------------------------------------------------- */
+/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = opérande à traiter. *
-* line = ligne tampon où imprimer l'opérande donné. *
+* Paramètres : object = objet dont l'instance est à consulter. *
* *
-* Description : Traduit un opérande en version humainement lisible. *
+* Description : Calcule l'empreinte sur 32 bits d'un objet. *
* *
-* Retour : - *
+* Retour : Valeur de représentation, unique pour l'objet ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_register_operand_print(const GRegisterOperand *operand, GBufferLine *line)
+static guint g_register_operand_hash(const GHashableObject *object)
{
- g_arch_register_print(operand->reg, line);
+ guint result; /* Valeur à retourner */
+ GHashableObjectInterface *iface; /* Interface utilisée */
+ GHashableObjectInterface *parent_iface; /* Interface parente */
+ GRegisterOperand *operand; /* Version spécialisée */
+
+ iface = G_HASHABLE_OBJECT_GET_IFACE(object);
+
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ result = parent_iface->hash(object);
+
+ operand = G_REGISTER_OPERAND(object);
+
+ result ^= g_hashable_object_hash(G_HASHABLE_OBJECT(operand->reg));
+
+ return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE CONSERVATION ET RESTAURATION */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = objet dont l'instance se veut unique. *
-* lock = précise le besoin en verrouillage. *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* Description : Charge un objet depuis un flux de données. *
* *
-* Retour : Empreinte de l'élément représenté. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock)
+static bool g_register_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
- guint result; /* Valeur à retourner */
- GArchOperandClass *class; /* Classe parente normalisée */
- GArchRegister *reg; /* Registre visé par l'opérande*/
+ bool result; /* Bilan à retourner */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *parent_iface; /* Interface parente */
+ GSerializableObject *reg; /* Registre récupéré */
+ GRegisterOperand *operand; /* Version spécialisée */
+
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
+
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ result = parent_iface->load(object, storage, fd);
+
+ if (result)
+ {
+ reg = g_object_storage_unpack_object(storage, fd, "registers");
- class = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class);
- result = class->hash(G_ARCH_OPERAND(operand), false);
+ if (reg == NULL)
+ result = false;
- reg = g_register_operand_get_register(operand);
+ else
+ {
+ operand = G_REGISTER_OPERAND(object);
- result ^= g_arch_register_hash(reg);
+ operand->reg = G_ARCH_REGISTER(reg);
+
+ }
- g_object_unref(G_OBJECT(reg));
+ }
return result;
@@ -291,11 +471,11 @@ static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock)
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Charge un contenu depuis une mémoire tampon. *
+* Description : Sauvegarde un objet dans un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -303,61 +483,64 @@ static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock)
* *
******************************************************************************/
-static bool g_register_operand_load(GRegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_register_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- GSerializableObject *reg; /* Registre manipulé */
+ GRegisterOperand *operand; /* Version spécialisée */
+ off64_t reg_pos; /* Position renvoyant au reg. */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *parent_iface; /* Interface parente */
- parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class);
+ operand = G_REGISTER_OPERAND(object);
- result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
+ result = g_object_storage_store_object(storage, "registers", G_SERIALIZABLE_OBJECT(operand->reg), &reg_pos);
+ if (!result) goto exit;
- if (result)
- {
- reg = g_object_storage_unpack_object(storage, "registers", pbuf);
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
- result = (reg != NULL);
+ parent_iface = g_type_interface_peek_parent(iface);
- if (result)
- operand->reg = G_ARCH_REGISTER(reg);
+ result = parent_iface->store(object, storage, fd);
+ if (!result) goto exit;
- }
+ result = store_uleb128((uleb128_t []) { reg_pos }, fd);
+
+ exit:
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : operand = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : builder = objet dont l'instance est exportable. *
+* flags = éventuelles indications pour l'opération. *
+* out = chaîne de caractères mise en place. [OUT] *
* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
+* Description : Exporte une chaîne de caractères à partir d'un objet. *
* *
* Retour : Bilan de l'opération. *
* *
-* Remarques : - *
+* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après *
+* usage. *
* *
******************************************************************************/
-static bool g_register_operand_store(GRegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_register_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
{
bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- GSerializableObject *reg; /* Registre manipulé */
+ const GRegisterOperand *operand; /* Version spécialisée */
- parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class);
+ operand = G_REGISTER_OPERAND(builder);
- result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
-
- if (result)
- {
- reg = G_SERIALIZABLE_OBJECT(operand->reg);
- result = g_object_storage_pack_object(storage, "registers", reg, pbuf);
- }
+ result = g_string_builder_to_string(G_STRING_BUILDER(operand->reg), flags, out);
return result;
diff --git a/src/arch/register-int.h b/src/arch/register-int.h
index f0b9af9..22ef2cc 100644
--- a/src/arch/register-int.h
+++ b/src/arch/register-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* register-int.h - définitions internes pour la représentation générique d'un registre
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,31 +26,15 @@
#include "register.h"
-#include "../analysis/storage/serialize-int.h"
-/* Produit une empreinte à partir d'un registre. */
-typedef guint (* reg_hash_fc) (const GArchRegister *);
-
-/* Compare un registre avec un autre. */
-typedef int (* reg_compare_fc) (const GArchRegister *, const GArchRegister *);
-
-/* Traduit un registre en version humainement lisible. */
-typedef void (* reg_print_fc) (const GArchRegister *, GBufferLine *);
-
/* Indique si le registre correspond à ebp ou similaire. */
typedef bool (* reg_is_base_pointer_fc) (const GArchRegister *);
/* Indique si le registre correspond à esp ou similaire. */
typedef bool (* reg_is_stack_pointer_fc) (const GArchRegister *);
-/* Charge un contenu depuis une mémoire tampon. */
-typedef bool (* load_register_fc) (GArchRegister *, GObjectStorage *, packed_buffer_t *);
-
-/* Sauvegarde un contenu dans une mémoire tampon. */
-typedef bool (* store_register_fc) (GArchRegister *, GObjectStorage *, packed_buffer_t *);
-
/* Représentation d'un registre (instance) */
struct _GArchRegister
@@ -64,15 +48,9 @@ struct _GArchRegisterClass
{
GObjectClass parent; /* A laisser en premier */
- reg_hash_fc hash; /* Production d'empreinte */
- reg_compare_fc compare; /* Comparaison de registres */
- reg_print_fc print; /* Impression du registre */
reg_is_base_pointer_fc is_bp; /* Correspondance avec ebp */
reg_is_stack_pointer_fc is_sp; /* Correspondance avec esp */
- load_register_fc load; /* Chargement depuis un tampon */
- store_register_fc store; /* Conservation dans un tampon */
-
};
diff --git a/src/arch/register.c b/src/arch/register.c
index f487419..6017373 100644
--- a/src/arch/register.c
+++ b/src/arch/register.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* registers.c - aides auxiliaires relatives aux registres Dalvik
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,6 +25,10 @@
#include "register-int.h"
+#include "../glibext/comparable-int.h"
+#include "../glibext/hashable-int.h"
+#include "../glibext/serialize-int.h"
+#include "../glibext/strbuilder-int.h"
@@ -34,34 +38,26 @@
/* Initialise la classe des registres. */
static void g_arch_register_class_init(GArchRegisterClass *);
-/* Initialise une instance de registre. */
-static void g_arch_register_init(GArchRegister *);
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_arch_register_comparable_object_iface_init(GComparableObjectInterface *);
+
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_arch_register_hashable_object_iface_init(GHashableObjectInterface *);
/* Procède à l'initialisation de l'interface de sérialisation. */
static void g_arch_register_serializable_init(GSerializableObjectInterface *);
-/* Supprime toutes les références externes. */
-static void g_arch_register_dispose(GArchRegister *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_arch_register_finalize(GArchRegister *);
-
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_arch_register_string_builder_iface_init(GStringBuilderInterface *);
+/* Initialise une instance de registre. */
+static void g_arch_register_init(GArchRegister *);
-/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
-
-
-/* Charge un contenu depuis une mémoire tampon. */
-static bool _g_arch_register_load(GArchRegister *, GObjectStorage *, packed_buffer_t *);
-
-/* Charge un contenu depuis une mémoire tampon. */
-static bool g_arch_register_load(GArchRegister *, GObjectStorage *, packed_buffer_t *);
-
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool _g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buffer_t *);
+/* Supprime toutes les références externes. */
+static void g_arch_register_dispose(GObject *);
-/* Sauvegarde un contenu dans une mémoire tampon. */
-static bool g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buffer_t *);
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_register_finalize(GObject *);
@@ -72,7 +68,10 @@ static bool g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buff
/* Indique le type défini pour une représentation d'un registre. */
G_DEFINE_TYPE_WITH_CODE(GArchRegister, g_arch_register, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_register_serializable_init));
+ G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_arch_register_comparable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_arch_register_hashable_object_iface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_register_serializable_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_arch_register_string_builder_iface_init));
/******************************************************************************
@@ -93,20 +92,18 @@ static void g_arch_register_class_init(GArchRegisterClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_register_dispose;
- object->finalize = (GObjectFinalizeFunc)g_arch_register_finalize;
-
- klass->load = (load_register_fc)_g_arch_register_load;
- klass->store = (store_register_fc)_g_arch_register_store;
+ object->dispose = g_arch_register_dispose;
+ object->finalize = g_arch_register_finalize;
}
+
/******************************************************************************
* *
-* Paramètres : reg = instance à initialiser. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Initialise une instance de registre. *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
* *
* Retour : - *
* *
@@ -114,8 +111,9 @@ static void g_arch_register_class_init(GArchRegisterClass *klass)
* *
******************************************************************************/
-static void g_arch_register_init(GArchRegister *reg)
+static void g_arch_register_comparable_object_iface_init(GComparableObjectInterface *iface)
{
+ iface->compare = NULL;
}
@@ -124,7 +122,7 @@ static void g_arch_register_init(GArchRegister *reg)
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Procède à l'initialisation de l'interface de sérialisation. *
+* Description : Procède à l'initialisation de l'interface de détermination. *
* *
* Retour : - *
* *
@@ -132,19 +130,18 @@ static void g_arch_register_init(GArchRegister *reg)
* *
******************************************************************************/
-static void g_arch_register_serializable_init(GSerializableObjectInterface *iface)
+static void g_arch_register_hashable_object_iface_init(GHashableObjectInterface *iface)
{
- iface->load = (load_serializable_object_cb)g_arch_register_load;
- iface->store = (store_serializable_object_cb)g_arch_register_store;
+ iface->hash = NULL;
}
/******************************************************************************
* *
-* Paramètres : reg = instance d'objet GLib à traiter. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Supprime toutes les références externes. *
+* Description : Procède à l'initialisation de l'interface de sérialisation. *
* *
* Retour : - *
* *
@@ -152,18 +149,19 @@ static void g_arch_register_serializable_init(GSerializableObjectInterface *ifac
* *
******************************************************************************/
-static void g_arch_register_dispose(GArchRegister *reg)
+static void g_arch_register_serializable_init(GSerializableObjectInterface *iface)
{
- G_OBJECT_CLASS(g_arch_register_parent_class)->dispose(G_OBJECT(reg));
+ iface->load = NULL;
+ iface->store = NULL;
}
/******************************************************************************
* *
-* Paramètres : reg = instance d'objet GLib à traiter. *
+* Paramètres : iface = interface GLib à initialiser. *
* *
-* Description : Procède à la libération totale de la mémoire. *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
* *
* Retour : - *
* *
@@ -171,58 +169,55 @@ static void g_arch_register_dispose(GArchRegister *reg)
* *
******************************************************************************/
-static void g_arch_register_finalize(GArchRegister *reg)
+static void g_arch_register_string_builder_iface_init(GStringBuilderInterface *iface)
{
- G_OBJECT_CLASS(g_arch_register_parent_class)->finalize(G_OBJECT(reg));
+ iface->to_string = NULL;
}
/******************************************************************************
* *
-* Paramètres : reg = opérande à consulter pour le calcul. *
+* Paramètres : reg = instance à initialiser. *
* *
-* Description : Produit une empreinte à partir d'un registre. *
+* Description : Initialise une instance de registre. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-guint g_arch_register_hash(const GArchRegister *reg)
+static void g_arch_register_init(GArchRegister *reg)
{
- return G_ARCH_REGISTER_GET_CLASS(reg)->hash(reg);
}
/******************************************************************************
* *
-* Paramètres : a = premier registre à consulter. *
-* b = second registre à consulter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
-* Description : Compare un registre avec un autre. *
+* Description : Supprime toutes les références externes. *
* *
-* Retour : Bilan de la comparaison. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b)
+static void g_arch_register_dispose(GObject *object)
{
- return G_ARCH_REGISTER_GET_CLASS(a)->compare(a, b);
+ G_OBJECT_CLASS(g_arch_register_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : reg = registre à transcrire. *
-* line = ligne tampon où imprimer l'opérande donné. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
-* Description : Traduit un registre en version humainement lisible. *
+* Description : Procède à la libération totale de la mémoire. *
* *
* Retour : - *
* *
@@ -230,9 +225,9 @@ int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b)
* *
******************************************************************************/
-void g_arch_register_print(const GArchRegister *reg, GBufferLine *line)
+static void g_arch_register_finalize(GObject *object)
{
- G_ARCH_REGISTER_GET_CLASS(reg)->print(reg, line);
+ G_OBJECT_CLASS(g_arch_register_parent_class)->finalize(object);
}
@@ -287,115 +282,3 @@ bool g_arch_register_is_stack_pointer(const GArchRegister *reg)
return result;
}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONSERVATION ET RECHARGEMENT DES DONNEES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool _g_arch_register_load(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
-
- result = true;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
-* *
-* Description : Charge un contenu depuis une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_arch_register_load(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchRegisterClass *class; /* Classe à activer */
-
- class = G_ARCH_REGISTER_GET_CLASS(reg);
-
- result = class->load(reg, storage, pbuf);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool _g_arch_register_store(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
-
- result = true;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : reg = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde un contenu dans une mémoire tampon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_arch_register_store(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- GArchRegisterClass *class; /* Classe à activer */
-
- class = G_ARCH_REGISTER_GET_CLASS(reg);
-
- result = class->store(reg, storage, pbuf);
-
- return result;
-
-}
diff --git a/src/arch/register.h b/src/arch/register.h
index 0265a73..16275e0 100644
--- a/src/arch/register.h
+++ b/src/arch/register.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* register.h - prototypes pour les aides auxiliaires relatives aux registres Dalvik
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,44 +25,19 @@
#define _ARCH_REGISTER_H
-#include <glib-object.h>
#include <stdbool.h>
-#include "../glibext/bufferline.h"
+#include "../glibext/helpers.h"
-/* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */
+#define G_TYPE_ARCH_REGISTER (g_arch_register_get_type())
+DECLARE_GTYPE(GArchRegister, g_arch_register, G, ARCH_REGISTER);
-#define G_TYPE_ARCH_REGISTER g_arch_register_get_type()
-#define G_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_REGISTER, GArchRegister))
-#define G_IS_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_REGISTER))
-#define G_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_REGISTER, GArchRegisterClass))
-#define G_IS_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_REGISTER))
-#define G_ARCH_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_REGISTER, GArchRegisterClass))
-/* Représentation d'un registre (instance) */
-typedef struct _GArchRegister GArchRegister;
-
-/* Représentation d'un registre (classe) */
-typedef struct _GArchRegisterClass GArchRegisterClass;
-
-
-/* Indique le type défini pour une représentation d'un registre. */
-GType g_arch_register_get_type(void);
-
-/* Produit une empreinte à partir d'un registre. */
-guint g_arch_register_hash(const GArchRegister *);
-
-/* Compare un registre avec un autre. */
-int g_arch_register_compare(const GArchRegister *, const GArchRegister *);
-
-/* Traduit un registre en version humainement lisible. */
-void g_arch_register_print(const GArchRegister *, GBufferLine *);
-
/* Indique si le registre correspond à ebp ou similaire. */
bool g_arch_register_is_base_pointer(const GArchRegister *);
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index 42136e2..7a11deb 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -30,7 +30,6 @@
#include <stdint.h>
-#include "archbase.h"
#include "../common/cpp.h"
#include "../common/datatypes.h"
#include "../common/packed.h"
@@ -297,4 +296,33 @@ char *mrange_length_to_string(const mrange_t *, MemoryDataSize, char [VMPA_MAX_L
+/* ------------------- DEFINITION D'UN ESPACE RELATIVE EN MEMOIRE ------------------- */
+
+
+/* Couverture mémoire */
+typedef struct _rel_mrange_t
+{
+ uint32_t offset; /* Décalage depuis une ref. */
+ uint16_t length; /* Taille de la couverture */
+
+} rel_mrange_t;
+
+
+#define init_rel_mrange(rr, o, l) \
+ do \
+ { \
+ (rr)->offset = o; \
+ (rr)->length = l; \
+ } \
+ while (0);
+
+
+#define get_rel_mrange_offset(rr) \
+ (rr)->offset
+
+#define get_rel_mrange_length(rr) \
+ (rr)->length
+
+
+
#endif /* _ARCH_VMPA_H */
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 27ead1d..1056cb2 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -6,7 +6,6 @@ libcommon_la_SOURCES = \
array.h array.c \
asm.h asm.c \
bconst.h \
- bits.h bits.c \
compression.h compression.c \
cpp.h \
cpu.h cpu.c \
@@ -21,7 +20,6 @@ libcommon_la_SOURCES = \
packed.h packed.c \
pathname.h pathname.c \
pearson.h pearson.c \
- shuffle.h shuffle.c \
sort.h sort.c \
sqlite.h sqlite.c \
szstr.h \
@@ -49,11 +47,14 @@ endif
libcommon4_la_SOURCES = \
+ array.h array.c \
asm.h asm.c \
bits.h bits.c \
compiler.h \
+ cpp.h \
datatypes.h \
dllist.h dllist.c \
+ entropy.h entropy.c \
environment.h environment.c \
extstr.h extstr.c \
fnv1a.h fnv1a.c \
@@ -62,10 +63,38 @@ libcommon4_la_SOURCES = \
macros.h \
packed.h packed.c \
pathname.h pathname.c \
+ shuffle.h shuffle.c \
sort.h sort.c \
+ szbin.h \
xdg.h xdg.c
-libcommon4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS)
+if BUILD_CURL_SUPPORT
+
+libcommon4_la_SOURCES += \
+ curl.h curl.c
+
+endif
+
+if BUILD_JSONGLIB_SUPPORT
+
+libcommon4_la_SOURCES += \
+ json.h json.c
+
+endif
+
+libcommon4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS) $(LIBJSONGLIB_CFLAGS)
+
+if BUILD_CURL_SUPPORT
+
+libcommon4_la_CFLAGS += $(LIBCURL_CFLAGS)
+
+endif
+
+if BUILD_JSONGLIB_SUPPORT
+
+libcommon4_la_CFLAGS += $(LIBJSONGLIB_CFLAGS)
+
+endif
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
diff --git a/src/common/bits.c b/src/common/bits.c
index 37e3141..27296f2 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -31,6 +31,8 @@
#include "asm.h"
+#include "io.h"
+#include "leb128.h"
@@ -50,7 +52,8 @@ struct _bitfield_t
/* Taille des mots intégrés */
-#define BF_WORD_SIZE (sizeof(unsigned long) * 8)
+#define BF_WORD_BIT_SIZE (sizeof(unsigned long) * 8)
+#define BF_WORD_BYTE_SIZE sizeof(unsigned long)
/* Crée un champ de bits initialisé à zéro. */
@@ -82,10 +85,10 @@ static bitfield_t *_create_bit_field(size_t length)
size_t needed; /* Nombre de mots à allouer */
size_t base; /* Allocation de base en octets*/
- needed = length / (sizeof(unsigned long) * 8);
- if (length % (sizeof(unsigned long) * 8) != 0) needed++;
+ needed = length / BF_WORD_BIT_SIZE;
+ if (length % BF_WORD_BIT_SIZE != 0) needed++;
- base = sizeof(bitfield_t) + needed * sizeof(unsigned long);
+ base = sizeof(bitfield_t) + needed * BF_WORD_BYTE_SIZE;
result = malloc(base);
@@ -148,7 +151,7 @@ bitfield_t *dup_bit_field(const bitfield_t *field)
result = _create_bit_field(field->length);
- memcpy(result->bits, field->bits, result->used_words * sizeof(unsigned long));
+ memcpy(result->bits, field->bits, result->used_words * BF_WORD_BYTE_SIZE);
return result;
@@ -191,7 +194,7 @@ void copy_bit_field(bitfield_t *dest, const bitfield_t *src)
{
assert(dest->length == src->length);
- memcpy(dest->bits, src->bits, dest->used_words * sizeof(unsigned long));
+ memcpy(dest->bits, src->bits, dest->used_words * BF_WORD_BYTE_SIZE);
}
@@ -217,8 +220,8 @@ void truncate_bit_field(bitfield_t **field, size_t length)
_field = *field;
- needed = length / (sizeof(unsigned long) * 8);
- if (length % (sizeof(unsigned long) * 8) != 0) needed++;
+ needed = length / BF_WORD_BIT_SIZE;
+ if (length % BF_WORD_BIT_SIZE != 0) needed++;
if (needed <= _field->allocated_words)
{
@@ -263,10 +266,10 @@ void resize_bit_field(bitfield_t **field, size_t length)
{
/* Redimensionnement */
- needed = length / (sizeof(unsigned long) * 8);
- if (length % (sizeof(unsigned long) * 8) != 0) needed++;
+ needed = length / BF_WORD_BIT_SIZE;
+ if (length % BF_WORD_BIT_SIZE != 0) needed++;
- base = sizeof(bitfield_t) + needed * sizeof(unsigned long);
+ base = sizeof(bitfield_t) + needed * BF_WORD_BYTE_SIZE;
/* Initialisation, si nécessaire */
@@ -275,8 +278,8 @@ void resize_bit_field(bitfield_t **field, size_t length)
*field = realloc(_field, base);
_field = *field;
- last = _field->length / (sizeof(unsigned long) * 8);
- remaining = _field->length % (sizeof(unsigned long) * 8);
+ last = _field->length / BF_WORD_BIT_SIZE;
+ remaining = _field->length % BF_WORD_BIT_SIZE;
if (remaining != 0)
{
@@ -367,7 +370,7 @@ int compare_bit_fields(const bitfield_t *a, const bitfield_t *b)
else
{
- final = a->length % (8 * sizeof(unsigned long));
+ final = a->length % BF_WORD_BIT_SIZE;
if (final == 0)
final = ~0lu;
@@ -414,7 +417,7 @@ int compare_bit_fields(const bitfield_t *a, const bitfield_t *b)
void reset_all_in_bit_field(bitfield_t *field)
{
- memset(field->bits, 0u, field->used_words * sizeof(unsigned long));
+ memset(field->bits, 0u, field->used_words * BF_WORD_BYTE_SIZE);
}
@@ -433,7 +436,35 @@ void reset_all_in_bit_field(bitfield_t *field)
void set_all_in_bit_field(bitfield_t *field)
{
- memset(field->bits, ~0u, field->used_words * sizeof(unsigned long));
+ memset(field->bits, ~0u, field->used_words * BF_WORD_BYTE_SIZE);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à modifier. *
+* first = indice du premier bit à traiter. *
+* *
+* Description : Bascule à 0 une partie d'un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_in_bit_field(bitfield_t *field, size_t first)
+{
+ size_t index; /* Cellule de tableau visée */
+ size_t remaining; /* Nombre de bits restants */
+
+ assert(first < field->length);
+
+ index = first / BF_WORD_BIT_SIZE;
+ remaining = first % BF_WORD_BIT_SIZE;
+
+ field->bits[index] &= ~(1ul << remaining);
}
@@ -452,7 +483,7 @@ void set_all_in_bit_field(bitfield_t *field)
* *
******************************************************************************/
-void reset_in_bit_field(bitfield_t *field, size_t first, size_t count)
+void reset_multi_in_bit_field(bitfield_t *field, size_t first, size_t count)
{
size_t last; /* Point d'arrêt de la boucle */
size_t i; /* Boucle de parcours */
@@ -465,8 +496,8 @@ void reset_in_bit_field(bitfield_t *field, size_t first, size_t count)
for (i = first; i < last; i++)
{
- index = i / (sizeof(unsigned long) * 8);
- remaining = i % (sizeof(unsigned long) * 8);
+ index = i / BF_WORD_BIT_SIZE;
+ remaining = i % BF_WORD_BIT_SIZE;
field->bits[index] &= ~(1ul << remaining);
@@ -479,6 +510,34 @@ void reset_in_bit_field(bitfield_t *field, size_t first, size_t count)
* *
* Paramètres : field = champ de bits à modifier. *
* first = indice du premier bit à traiter. *
+* *
+* Description : Bascule à 1 une partie d'un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_in_bit_field(bitfield_t *field, size_t first)
+{
+ size_t index; /* Cellule de tableau visée */
+ size_t remaining; /* Nombre de bits restants */
+
+ assert(first < field->length);
+
+ index = first / BF_WORD_BIT_SIZE;
+ remaining = first % BF_WORD_BIT_SIZE;
+
+ field->bits[index] |= (1ul << remaining);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à modifier. *
+* first = indice du premier bit à traiter. *
* count = nombre de bits à marquer. *
* *
* Description : Bascule à 1 une partie d'un champ de bits. *
@@ -489,7 +548,7 @@ void reset_in_bit_field(bitfield_t *field, size_t first, size_t count)
* *
******************************************************************************/
-void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
+void set_multi_in_bit_field(bitfield_t *field, size_t first, size_t count)
{
size_t last; /* Point d'arrêt de la boucle */
size_t i; /* Boucle de parcours */
@@ -502,8 +561,8 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
for (i = first; i < last; i++)
{
- index = i / (sizeof(unsigned long) * 8);
- remaining = i % (sizeof(unsigned long) * 8);
+ index = i / BF_WORD_BIT_SIZE;
+ remaining = i % BF_WORD_BIT_SIZE;
field->bits[index] |= (1ul << remaining);
@@ -587,12 +646,12 @@ void or_bit_field_at(bitfield_t *dest, const bitfield_t *src, size_t first)
assert((first + src->length) <= dest->length);
- start = first / (sizeof(unsigned long) * 8);
- offset = first % (sizeof(unsigned long) * 8);
+ start = first / BF_WORD_BIT_SIZE;
+ offset = first % BF_WORD_BIT_SIZE;
- remaining = (first + src->length) % (sizeof(unsigned long) * 8);
+ remaining = (first + src->length) % BF_WORD_BIT_SIZE;
- if ((first + src->length) % (sizeof(unsigned long) * 8) > 0)
+ if ((first + src->length) % BF_WORD_BIT_SIZE > 0)
last_iter = src->used_words;
else
last_iter = src->used_words - 1;
@@ -605,7 +664,7 @@ void or_bit_field_at(bitfield_t *dest, const bitfield_t *src, size_t first)
word = 0;
if (i > 0 && offset > 0)
- word |= src->bits[i - 1] >> (sizeof(unsigned long) * 8 - offset);
+ word |= src->bits[i - 1] >> (BF_WORD_BIT_SIZE - offset);
if (i == last_iter && remaining > 0)
word &= (1ul << remaining) - 1;
@@ -638,8 +697,8 @@ bool test_in_bit_field(const bitfield_t *field, size_t n)
assert(n < field->length);
- index = n / (sizeof(unsigned long) * 8);
- remaining = n % (sizeof(unsigned long) * 8);
+ index = n / BF_WORD_BIT_SIZE;
+ remaining = n % BF_WORD_BIT_SIZE;
result = field->bits[index] & (1ul << remaining);
@@ -670,8 +729,8 @@ bool test_and_set_in_bit_field(bitfield_t *field, size_t n)
assert(n < field->length);
- index = n / (sizeof(unsigned long) * 8);
- remaining = n % (sizeof(unsigned long) * 8);
+ index = n / BF_WORD_BIT_SIZE;
+ remaining = n % BF_WORD_BIT_SIZE;
bits = field->bits + index;
@@ -713,8 +772,8 @@ static bool test_state_in_bit_field(const bitfield_t *field, size_t first, size_
for (i = first; i < last; i++)
{
- index = i / (sizeof(unsigned long) * 8);
- remaining = i % (sizeof(unsigned long) * 8);
+ index = i / BF_WORD_BIT_SIZE;
+ remaining = i % BF_WORD_BIT_SIZE;
current = field->bits[index] & (1ul << remaining);
@@ -805,14 +864,30 @@ static bool test_state_within_bit_field(const bitfield_t *field, size_t first, c
unsigned long bitmask; /* Masque à appliquer */
unsigned long test; /* Valeur résultante du test */
- result = true;
+ /**
+ * Si un masque est à appliquer avec débordement, les bits débordés sont considérés
+ * comme initialisés à la valeur par défaut.
+ */
+
+ if ((first + mask->length) > field->length)
+ {
+ assert(mask->length > 0);
+
+ result = (state == field->default_state);
+ if (!result) goto done;
+
+ if (first >= field->length)
+ goto done;
- assert((first + mask->length) <= field->length);
+ }
- start = first / (sizeof(unsigned long) * 8);
- offset = first % (sizeof(unsigned long) * 8);
+ else
+ result = true;
- remaining = mask->length % (sizeof(unsigned long) * 8);
+ start = first / BF_WORD_BIT_SIZE;
+ offset = first % BF_WORD_BIT_SIZE;
+
+ remaining = mask->length % BF_WORD_BIT_SIZE;
if (remaining == 0)
finalcut = ~0lu;
@@ -830,7 +905,7 @@ static bool test_state_within_bit_field(const bitfield_t *field, size_t first, c
{
word = field->bits[windex] >> offset;
if ((windex + 1) < field->used_words)
- word |= field->bits[windex + 1] << (sizeof(unsigned long) * 8 - offset);
+ word |= field->bits[windex + 1] << (BF_WORD_BIT_SIZE - offset);
}
bitmask = mask->bits[i];
@@ -849,6 +924,8 @@ static bool test_state_within_bit_field(const bitfield_t *field, size_t first, c
}
+ done:
+
return result;
}
@@ -934,7 +1011,7 @@ size_t find_next_set_in_bit_field(const bitfield_t *field, const size_t *prev)
}
else
{
- i = *prev / BF_WORD_SIZE;
+ i = *prev / BF_WORD_BIT_SIZE;
if (i >= field->used_words)
{
@@ -944,9 +1021,9 @@ size_t find_next_set_in_bit_field(const bitfield_t *field, const size_t *prev)
word = field->bits[i];
- last_pos = *prev % BF_WORD_SIZE;
+ last_pos = *prev % BF_WORD_BIT_SIZE;
- if ((last_pos + 1) == BF_WORD_SIZE)
+ if ((last_pos + 1) == BF_WORD_BIT_SIZE)
goto next_word;
word &= ~((1lu << (last_pos + 1)) - 1);
@@ -957,7 +1034,7 @@ size_t find_next_set_in_bit_field(const bitfield_t *field, const size_t *prev)
if (found > 0)
{
- result = i * BF_WORD_SIZE + found - 1;
+ result = i * BF_WORD_BIT_SIZE + found - 1;
goto done;
}
@@ -973,7 +1050,7 @@ size_t find_next_set_in_bit_field(const bitfield_t *field, const size_t *prev)
if (found > 0)
{
- result = i * BF_WORD_SIZE + found - 1;
+ result = i * BF_WORD_BIT_SIZE + found - 1;
/**
* Validation des bornes finales, pour le dernier mot.
@@ -1148,7 +1225,7 @@ size_t popcount_for_bit_field(const bitfield_t *field)
{
value = field->bits[i];
- if (remaining < (8 * sizeof(unsigned long)))
+ if (remaining < BF_WORD_BIT_SIZE)
value &= (1lu << remaining) - 1;
#if __WORDSIZE == 64
@@ -1159,7 +1236,7 @@ size_t popcount_for_bit_field(const bitfield_t *field)
# error "Unkown word size"
#endif
- remaining -= 8 * sizeof(unsigned long);
+ remaining -= BF_WORD_BIT_SIZE;
}
@@ -1190,8 +1267,6 @@ void output_bit_field(const bitfield_t *field)
printf("[len=%zu] \n", field->length);
-#define MAX_BITS (sizeof(unsigned long) * 8)
-
for (i = 0; i < field->used_words; i++)
{
value = field->bits[i];
@@ -1199,9 +1274,9 @@ void output_bit_field(const bitfield_t *field)
if (i > 0)
printf("| ");
- for (k = 0; k < MAX_BITS; k++)
+ for (k = 0; k < BF_WORD_BIT_SIZE; k++)
{
- if ((i * MAX_BITS + k) >= field->length)
+ if ((i * BF_WORD_BIT_SIZE + k) >= field->length)
break;
printf("%c", value & (1lu << k) ? '1' : '.');
@@ -1218,3 +1293,133 @@ void output_bit_field(const bitfield_t *field)
}
#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : fd = flux ouvert en lecture. *
+* length = éventuelle indication de la taille du champ ? *
+* def_state = éventuelle indication de l'état par défaut ? *
+* endian = ordre des bits dans la source. *
+* *
+* Description : Restaure un champ de bits depuis un flux ouvert. *
+* *
+* Retour : Adresse du champs de bits mis en place, NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bitfield_t *load_bit_field(int fd, const size_t *length, const bool *def_state, SourceEndian endian)
+{
+ bitfield_t *result; /* Structure à retourner */
+ size_t final_length; /* Nombre de bits représentés */
+ uleb128_t leb128_value; /* Valeur LEB128 chargée */
+ bool status; /* Bilan d'une lecture */
+ bool final_default_state; /* Etat d'initialisation */
+ uint8_t u8_value; /* Valeur sur 8 bits chargée */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ if (length != NULL)
+ final_length = *length;
+ else
+ {
+ status = load_uleb128(&leb128_value, fd);
+ if (!status) goto exit;
+
+ final_length = leb128_value;
+
+ }
+
+ if (def_state != NULL)
+ final_default_state = *def_state;
+
+ else
+ {
+ status = load_u8(fd, &u8_value);
+ if (!status) goto exit;
+
+ final_default_state = !!u8_value;
+
+ }
+
+ result = _create_bit_field(final_length);
+
+ result->default_state = final_default_state;
+
+ for (i = 0; i < result->used_words; i++)
+ {
+ status = load_uleb128(&leb128_value, fd);
+
+ if (status)
+ result->bits[i] = leb128_value;
+
+ else
+ {
+ delete_bit_field(result);
+ result = NULL;
+ break;
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à consulter. *
+* fd = flux ouvert en écriture. *
+* skip_len = saute la sauvegarde de la taille du champ ? *
+* skip_def = saute la sauvegarde de l'état par défaut ? *
+* endian = ordre des bits dans la source. *
+* *
+* Description : Sauvegarde un champ de bits dans un flux ouvert. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool store_bit_field(const bitfield_t *field, int fd, bool skip_len, bool skip_def, SourceEndian endian)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ if (skip_len)
+ result = true;
+ else
+ {
+ result = store_uleb128((const uleb128_t []) { field->length }, fd);
+ if (!result) goto exit;
+ }
+
+ if (skip_def)
+ result = true;
+ else
+ {
+ result = store_u8(fd, field->default_state);
+ if (!result) goto exit;
+ }
+
+ for (i = 0; i < field->used_words; i++)
+ {
+ result = store_uleb128((const uleb128_t []) { field->bits[i] }, fd);
+
+ if (!result)
+ break;
+
+ }
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/common/bits.h b/src/common/bits.h
index a66c6f0..d9c83c8 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -29,6 +29,9 @@
#include <sys/types.h>
+#include "datatypes.h"
+
+
/* Champ de bits simple */
typedef struct _bitfield_t bitfield_t;
@@ -65,10 +68,16 @@ void reset_all_in_bit_field(bitfield_t *);
void set_all_in_bit_field(bitfield_t *);
/* Bascule à 0 une partie d'un champ de bits. */
-void reset_in_bit_field(bitfield_t *, size_t, size_t);
+void reset_in_bit_field(bitfield_t *, size_t);
+
+/* Bascule à 0 une partie d'un champ de bits. */
+void reset_multi_in_bit_field(bitfield_t *, size_t, size_t);
/* Bascule à 1 une partie d'un champ de bits. */
-void set_in_bit_field(bitfield_t *, size_t, size_t);
+void set_in_bit_field(bitfield_t *, size_t);
+
+/* Bascule à 1 une partie d'un champ de bits. */
+void set_multi_in_bit_field(bitfield_t *, size_t, size_t);
/* Réalise une opération ET logique entre deux champs de bits. */
void and_bit_field(bitfield_t *, const bitfield_t *);
@@ -113,6 +122,12 @@ void output_bit_field(const bitfield_t *);
#endif
+/* Restaure un champ de bits depuis un flux ouvert. */
+bitfield_t *load_bit_field(int, const size_t *, const bool *, SourceEndian);
+
+/* Sauvegarde un champ de bits dans un flux ouvert. */
+bool store_bit_field(const bitfield_t *, int, bool, bool, SourceEndian);
+
#endif /* _COMMON_BITS_H */
diff --git a/src/common/compiler.h b/src/common/compiler.h
index 2585e47..65df8a4 100644
--- a/src/common/compiler.h
+++ b/src/common/compiler.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* compiler.h - prototypes pour le regroupement d'astuces à destination du compilateur
*
- * Copyright (C) 2024 Cyrille Bagard
+ * Copyright (C) 2024-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,5 +34,19 @@
#define __weak __attribute__((weak))
+/**
+ * Contournement des avertissements de la forme suivante :
+ *
+ * assignment to 'const char * const*' from incompatible pointer type 'char **' [-Wincompatible-pointer-types]
+ *
+ * Références :
+ * - https://www.reddit.com/r/C_Programming/comments/qa2231/const_char_const_and_char_are_incompatible/
+ * - https://stackoverflow.com/questions/78125/why-cant-i-convert-char-to-a-const-char-const-in-c
+ * - https://c-faq.com/ansi/constmismatch.html
+ */
+
+#define CONST_ARRAY_CAST(a, tp) (const tp **)a
+
+
#endif /* _COMMON_COMPILER_H */
diff --git a/src/common/cpp.h b/src/common/cpp.h
index 39e7676..4ebad82 100644
--- a/src/common/cpp.h
+++ b/src/common/cpp.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* cpp.h - prototypes pour avoir à disposition un langage C plus plus mieux
*
- * Copyright (C) 2010-2020 Cyrille Bagard
+ * Copyright (C) 2010-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -31,12 +31,27 @@
/**
+ * Fournit la taille d'une chaîne statique.
+ */
+#define STATIC_STR_SIZE(s) (sizeof(s) - 1)
+
+
+/**
* Fournit la taille d'un tableau statique.
*/
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/**
+ * Facilite la transmission d'arguement pour des fonctions
+ * comme strncmp() et Cie.
+ */
+#define SL(str) str, strlen(str)
+
+#define STCSL(str) str, STATIC_STR_SIZE(str)
+
+
+/**
* Détermine la taille de la plus longue chaîne de caractères
* correspondant à un type donné.
*/
diff --git a/src/common/curl.c b/src/common/curl.c
index 573180f..e9fb92f 100644
--- a/src/common/curl.c
+++ b/src/common/curl.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* curl.c - encapsulation des fonctionnalités de cURL
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2022-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,14 +28,62 @@
#include <string.h>
+#include "../core/global.h"
+
+
+
+/* Mémorise un volume de données transférées. */
+static int track_curl_data_transfers(CURL *, curl_infotype, char *, size_t, void *);
/* Mémorise les données reçues en réponse à une requête. */
-static size_t receive_data_from_internet(void *, size_t, size_t, curl_net_data_t *);
+static size_t receive_data_from_internet(void *, size_t, size_t, sized_binary_t *);
/******************************************************************************
* *
+* Paramètres : handle = gestionnaire de la requête cURL concernée. *
+* type = type de transfert réalisé. *
+* data = pointeur vers les données manipulées. *
+* size = quantité de données transférées. *
+* unused = adresse non utilisée ici. *
+* *
+* Description : Mémorise un volume de données transférées. *
+* *
+* Retour : CURLE_OK. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int track_curl_data_transfers(CURL *handle, curl_infotype type, char *data, size_t size, void *unused)
+{
+ switch (type)
+ {
+ case CURLINFO_HEADER_IN:
+ case CURLINFO_DATA_IN:
+ /*case CURLINFO_SSL_DATA_IN:*/
+ update_network_stats(size, 0);
+ break;
+
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_DATA_OUT:
+ /*case CURLINFO_SSL_DATA_OUT:*/
+ update_network_stats(0, size);
+ break;
+
+ default:
+ break;
+
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : contents = contenu nouveau en arrivance d'Internet. *
* size = taille d'un élément reçu. *
* nmemb = quantité de ces éléments. *
@@ -49,19 +97,19 @@ static size_t receive_data_from_internet(void *, size_t, size_t, curl_net_data_t
* *
******************************************************************************/
-static size_t receive_data_from_internet(void *contents, size_t size, size_t nmemb, curl_net_data_t *data)
+static size_t receive_data_from_internet(void *contents, size_t size, size_t nmemb, sized_binary_t *data)
{
size_t realsize; /* Taille brute en octets */
realsize = size * nmemb;
- data->memory = realloc(data->memory, data->size + realsize + 1);
+ data->data = realloc(data->data, data->size + realsize + 1);
- memcpy(&(data->memory[data->size]), contents, realsize);
+ memcpy(&(data->data[data->size]), contents, realsize);
data->size += realsize;
- data->memory[data->size] = 0;
+ data->data[data->size] = 0;
return realsize;
@@ -85,7 +133,7 @@ static size_t receive_data_from_internet(void *contents, size_t size, size_t nme
* *
******************************************************************************/
-bool send_http_get_request(const char *url, char * const headers[], size_t hcount, const char *cookies, setup_extra_curl_cb ecb, curl_net_data_t *resp)
+bool send_http_get_request(const char *url, char * const headers[], size_t hcount, const char *cookies, setup_extra_curl_cb ecb, sized_binary_t *resp)
{
bool result; /* Bilan d'opération à renvoyer*/
CURL *req; /* Requête HTTP */
@@ -95,12 +143,14 @@ bool send_http_get_request(const char *url, char * const headers[], size_t hcoun
result = false;
- resp->memory = NULL;
- resp->size = 0;
+ init_sized_binary(resp);
req = curl_easy_init();
if (req == NULL) goto exit;
+ curl_easy_setopt(req, CURLOPT_DEBUGFUNCTION, track_curl_data_transfers);
+ curl_easy_setopt(req, CURLOPT_VERBOSE, 1L);
+
curl_easy_setopt(req, CURLOPT_URL, url);
/* Entêtes à transmettre */
@@ -165,7 +215,7 @@ bool send_http_get_request(const char *url, char * const headers[], size_t hcoun
* *
******************************************************************************/
-bool send_http_post_request(const char *url, char * const headers[], size_t hcount, const char *cookies, const curl_net_data_t *payload, setup_extra_curl_cb ecb, curl_net_data_t *resp)
+bool send_http_post_request(const char *url, char * const headers[], size_t hcount, const char *cookies, const sized_binary_t *payload, setup_extra_curl_cb ecb, sized_binary_t *resp)
{
bool result; /* Bilan d'opération à renvoyer*/
CURL *req; /* Requête HTTP */
@@ -175,12 +225,14 @@ bool send_http_post_request(const char *url, char * const headers[], size_t hcou
result = false;
- resp->memory = NULL;
- resp->size = 0;
+ init_sized_binary(resp);
req = curl_easy_init();
if (req == NULL) goto exit;
+ curl_easy_setopt(req, CURLOPT_DEBUGFUNCTION, track_curl_data_transfers);
+ curl_easy_setopt(req, CURLOPT_VERBOSE, 1L);
+
curl_easy_setopt(req, CURLOPT_URL, url);
/* Entêtes à transmettre */
@@ -205,7 +257,7 @@ bool send_http_post_request(const char *url, char * const headers[], size_t hcou
curl_easy_setopt(req, CURLOPT_POST, 1);
- curl_easy_setopt(req, CURLOPT_POSTFIELDS, payload->memory);
+ curl_easy_setopt(req, CURLOPT_POSTFIELDS, payload->data);
curl_easy_setopt(req, CURLOPT_POSTFIELDSIZE, payload->size);
/* Emission de la requête */
diff --git a/src/common/curl.h b/src/common/curl.h
index 02d9e91..1fc8f54 100644
--- a/src/common/curl.h
+++ b/src/common/curl.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* curl.h - prototypes pour l'encapsulation des fonctionnalités de cURL
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2022-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,14 +29,8 @@
#include <curl/curl.h>
+#include "szbin.h"
-/* Données échangées avec Internet */
-typedef struct _curl_net_data_t
-{
- char *memory; /* Zone de mémoire allouée */
- size_t size; /* Quantité de données */
-
-} curl_net_data_t;
/* Prototype pour une intervention complémentaire dans la préparation des requêtes */
@@ -44,10 +38,10 @@ typedef CURLcode (* setup_extra_curl_cb) (CURL *);
/* Mémorise les données reçues en réponse à une requête. */
-bool send_http_get_request(const char *, char * const [], size_t, const char *, setup_extra_curl_cb, curl_net_data_t *);
+bool send_http_get_request(const char *, char * const [], size_t, const char *, setup_extra_curl_cb, sized_binary_t *);
/* Mémorise les données reçues en réponse à une requête. */
-bool send_http_post_request(const char *, char * const [], size_t, const char *, const curl_net_data_t *, setup_extra_curl_cb, curl_net_data_t *);
+bool send_http_post_request(const char *, char * const [], size_t, const char *, const sized_binary_t *, setup_extra_curl_cb, sized_binary_t *);
diff --git a/src/common/datatypes.h b/src/common/datatypes.h
index 3983267..248f4a1 100644
--- a/src/common/datatypes.h
+++ b/src/common/datatypes.h
@@ -52,5 +52,35 @@ typedef enum _SourceEndian
} SourceEndian;
+/* Taille des données intégrées */
+typedef enum _MemoryDataSize
+{
+ MDS_UNDEFINED = 0x0, /* Taille non définie */
+
+ MDS_4_BITS_UNSIGNED = 0x1, /* Opérande sur 4 bits n.-s. */
+ MDS_8_BITS_UNSIGNED = 0x2, /* Opérande sur 8 bits n.-s. */
+ MDS_16_BITS_UNSIGNED = 0x3, /* Opérande sur 16 bits n.-s. */
+ MDS_32_BITS_UNSIGNED = 0x4, /* Opérande sur 32 bits n.-s. */
+ MDS_64_BITS_UNSIGNED = 0x5, /* Opérande sur 64 bits n.-s. */
+
+ MDS_4_BITS_SIGNED = 0x8 | 0x1, /* Opérande sur 4 bits signés */
+ MDS_8_BITS_SIGNED = 0x8 | 0x2, /* Opérande sur 8 bits signés */
+ MDS_16_BITS_SIGNED = 0x8 | 0x3, /* Opérande sur 16 bits signés */
+ MDS_32_BITS_SIGNED = 0x8 | 0x4, /* Opérande sur 32 bits signés */
+ MDS_64_BITS_SIGNED = 0x8 | 0x5 /* Opérande sur 64 bits signés */
+
+} MemoryDataSize;
+
+#define MDS_RANGE(mds) ((mds & 0x7) - 1)
+#define MDS_SIGN 0x8
+#define MDS_IS_SIGNED(mds) (mds & MDS_SIGN)
+
+#define MDS_4_BITS MDS_4_BITS_UNSIGNED
+#define MDS_8_BITS MDS_8_BITS_UNSIGNED
+#define MDS_16_BITS MDS_16_BITS_UNSIGNED
+#define MDS_32_BITS MDS_32_BITS_UNSIGNED
+#define MDS_64_BITS MDS_64_BITS_UNSIGNED
+
+
#endif /* _COMMON_DATATYPES_H */
diff --git a/src/common/entropy.c b/src/common/entropy.c
new file mode 100644
index 0000000..8dae698
--- /dev/null
+++ b/src/common/entropy.c
@@ -0,0 +1,88 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * entropy.c - calcul de l'entropie d'un contenu binaire
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "entropy.h"
+
+
+#include <math.h>
+#include <string.h>
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = séquence d'octets à traiter. *
+* len = quantité de ces octets. *
+* bits = calcul en concidérant les bits et non les octets ? *
+* *
+* Description : Détermine l'entropie d'un contenu binaire. *
+* *
+* Retour : Valeur d'entropie du contenu fourni. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+double compute_entropy(const bin_t *data, size_t len, bool bits)
+{
+ double result; /* Valeur calculée à renvoyer */
+ unsigned long counters[256]; /* Décompte des valeurs */
+ const bin_t *d_max; /* Borne de fin de parcours #1 */
+ const bin_t *d_iter; /* Boucle de parcours #1 */
+ double log_2; /* Valeur constante de log2 */
+ unsigned long *c_max; /* Borne de fin de parcours #2 */
+ unsigned long *c_iter; /* Boucle de parcours #2 */
+ double freq; /* Fréquence liée à une valeur */
+
+ result = 0.0;
+
+ memset(counters, 0, sizeof(counters));
+
+ d_max = data + len;
+
+ for (d_iter = data; d_iter < d_max; d_iter++)
+ counters[*d_iter]++;
+
+ /**
+ * Explication du choix de log :
+ * https://stackoverflow.com/questions/990477/how-to-calculate-the-entropy-of-a-file/990646#990646
+ */
+
+ log_2 = log(bits ? 2.0 : 256.0);
+
+ c_max = counters + 256;
+
+ for (c_iter = counters; c_iter < c_max; c_iter++)
+ {
+ if (*c_iter == 0lu)
+ continue;
+
+ freq = ((double)*c_iter) / ((double)len);
+
+ result -= freq * (log(freq) / log_2);
+
+ }
+
+ return result;
+
+}
diff --git a/src/common/entropy.h b/src/common/entropy.h
new file mode 100644
index 0000000..cfd51ef
--- /dev/null
+++ b/src/common/entropy.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * entropy.h - prototypes pour le calcul de l'entropie d'un contenu binaire
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_ENTROPY_H
+#define _COMMON_ENTROPY_H
+
+
+#include <stdbool.h>
+#include <stddef.h>
+
+
+#include "../common/datatypes.h"
+
+
+
+/* Détermine l'entropie d'un contenu binaire. */
+double compute_entropy(const bin_t *, size_t, bool);
+
+
+
+#endif /* _COMMON_ENTROPY_H */
diff --git a/src/common/extstr.c b/src/common/extstr.c
index bd3491f..fe0bab4 100644
--- a/src/common/extstr.c
+++ b/src/common/extstr.c
@@ -636,7 +636,7 @@ const void *memcasemem(const void *haystack, size_t haystacklen, const void *nee
* *
* Description : Compare sans casse deux série d'octets entre elles. *
* *
-* Retour : Status de la comparaison des séries d'octets. *
+* Retour : Statut de la comparaison des séries d'octets. *
* *
* Remarques : - *
* *
diff --git a/src/common/fnv1a.c b/src/common/fnv1a.c
index a8afd0a..057d6c9 100644
--- a/src/common/fnv1a.c
+++ b/src/common/fnv1a.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* fnv1a.c - implémentaton du calcul rapide d'empreintes de chaînes
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -87,3 +87,34 @@ fnv64_t fnv_64a_hash(const char *str)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = données binaires à traiter. *
+* size = quantité de ces données. *
+* *
+* Description : Détermine l'empreinte FNV1a d'une séquence d'octets. *
+* *
+* Retour : Valeur calculée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+fnv64_t fnv_64a_hash_data(const uint8_t *data, size_t size)
+{
+ fnv64_t result; /* Valeur à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = FNV1A_64_INIT;
+
+ for (i = 0; i < size; i++)
+ {
+ result ^= (fnv64_t)data[i];
+ result *= FNV_64_PRIME;
+ }
+
+ return result;
+
+}
diff --git a/src/common/fnv1a.h b/src/common/fnv1a.h
index eec1460..4da3108 100644
--- a/src/common/fnv1a.h
+++ b/src/common/fnv1a.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* fnv1a.h - prototypes pour l'implémentaton du calcul rapide d'empreintes de chaînes
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -27,6 +27,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <sys/types.h>
/**
@@ -46,6 +47,9 @@ int cmp_fnv_64a(fnv64_t, fnv64_t);
/* Détermine l'empreinte FNV1a d'une chaîne de caractères. */
fnv64_t fnv_64a_hash(const char *);
+/* Détermine l'empreinte FNV1a d'une séquence d'octets. */
+fnv64_t fnv_64a_hash_data(const uint8_t *, size_t);
+
#endif /* _COMMON_FNV1A_H */
diff --git a/src/common/io.h b/src/common/io.h
index 7fe9d9d..1932b12 100644
--- a/src/common/io.h
+++ b/src/common/io.h
@@ -39,12 +39,69 @@
/* Lit des données depuis un flux local. */
bool safe_read(int, void *, size_t);
+#define load_u8(f, v) \
+ safe_read(f, v, sizeof(uint8_t));
+
+#define load_u16(f, v, e) \
+ ({ \
+ bool __ret; \
+ uint16_t __val; \
+ __ret = safe_read(f, &__val, sizeof(uint16_t)); \
+ __val = swap_u16(&__val, e); \
+ *(v) = __val; \
+ __ret; \
+ })
+
+#define load_u32(f, v, e) \
+ ({ \
+ bool __ret; \
+ uint32_t __val; \
+ __ret = safe_read(f, &__val, sizeof(uint32_t)); \
+ __val = swap_u32(&__val, e); \
+ *(v) = __val; \
+ __ret; \
+ })
+
+#define load_u64(f, v, e) \
+ ({ \
+ bool __ret; \
+ uint64_t __val; \
+ __ret = safe_read(f, &__val, sizeof(uint64_t)); \
+ __val = swap_u64(&__val, e); \
+ *(v) = __val; \
+ __ret; \
+ })
+
/* Lit des données depuis un flux local. */
ssize_t safe_read_partial(int, void *, size_t);
/* Ecrit des données dans un flux local. */
bool safe_write(int, const void *, size_t);
+#define store_u8(f, v) \
+ safe_write(f, (const uint8_t []){ v }, sizeof(uint8_t));
+
+#define store_u16(f, v, e) \
+ ({ \
+ uint16_t __val; \
+ __val = swap_u16((const uint16_t []){ v }, e); \
+ safe_write(f, &__val, sizeof(uint16_t)); \
+ })
+
+#define store_u32(f, v, e) \
+ ({ \
+ uint32_t __val; \
+ __val = swap_u32((const uint32_t []){ v }, e); \
+ safe_write(f, &__val, sizeof(uint32_t)); \
+ })
+
+#define store_u64(f, v, e) \
+ ({ \
+ uint64_t __val; \
+ __val = swap_u64((const uint64_t []){ v }, e); \
+ safe_write(f, &__val, sizeof(uint64_t)); \
+ })
+
/* Réceptionne des données depuis un flux réseau. */
bool safe_recv(int, void *, size_t, int);
diff --git a/src/common/json.c b/src/common/json.c
new file mode 100644
index 0000000..cb64822
--- /dev/null
+++ b/src/common/json.c
@@ -0,0 +1,203 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * json.c - manipulations génériques de données au format JSON
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "json.h"
+
+
+#include <assert.h>
+
+
+
+/******************************************************************************
+* *
+* Paramètres : root = racine d'une arborescence JSON chargée. *
+* query = chemin XPath d'une requête à mener. *
+* error = description d'une éventuelle erreur rencontrée. [OUT]*
+* *
+* Description : Détermine la présence d'un élément avec une valeur textuelle.*
+* *
+* Retour : true si le noeud existe et porte une chaîne comme valeur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool has_json_string_value(JsonNode *root, const char *xpath, GError **error)
+{
+ bool result; /* Bilan à retourner */
+ JsonNode *found; /* Accès direct aux trouvailles*/
+ JsonArray *array; /* Liste des résultats */
+ guint count; /* Taille de la liste */
+ JsonNode *node; /* Noeud portant la cible */
+ GValue value; /* Valeur correspondante */
+
+ result = false;
+
+ *error = NULL;
+ found = json_path_query(xpath, root, error);
+
+ if (found != NULL)
+ {
+ assert(*error == NULL);
+
+ array = json_node_get_array(found);
+
+ count = json_array_get_length(array);
+
+ if (count == 1)
+ {
+ node = json_array_get_element(array, 0);
+
+ memset(&value, 0, sizeof(GValue));
+ json_node_get_value(node, &value);
+
+ if (G_VALUE_HOLDS(&value, G_TYPE_STRING))
+ result = true;
+
+ }
+
+ json_node_unref(found);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : root = racine d'une arborescence JSON chargée. *
+* query = chemin XPath d'une requête à mener. *
+* error = description d'une éventuelle erreur rencontrée. [OUT]*
+* *
+* Description : Fournit le contenu d'un élément avec une valeur textuelle. *
+* *
+* Retour : Valeur trouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *get_json_string_value(JsonNode *root, const char *xpath, GError **error)
+{
+ char *result; /* Valeur à retourner */
+ JsonNode *found; /* Accès direct aux trouvailles*/
+ JsonArray *array; /* Liste des résultats */
+ guint count; /* Taille de la liste */
+ JsonNode *node; /* Noeud portant la cible */
+ GValue value; /* Valeur correspondante */
+ const gchar *raw; /* Valeur brute présente */
+
+ result = NULL;
+
+ *error = NULL;
+ found = json_path_query(xpath, root, error);
+
+ if (found != NULL)
+ {
+ assert(*error == NULL);
+
+ array = json_node_get_array(found);
+
+ count = json_array_get_length(array);
+
+ if (count == 1)
+ {
+ node = json_array_get_element(array, 0);
+
+ memset(&value, 0, sizeof(GValue));
+ json_node_get_value(node, &value);
+
+ if (G_VALUE_HOLDS(&value, G_TYPE_STRING))
+ {
+ raw = json_array_get_string_element(array, 0);
+ result = strdup(raw);
+ }
+
+ }
+
+ json_node_unref(found);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : root = racine d'une arborescence JSON chargée. *
+* query = chemin XPath d'une requête à mener. *
+* error = description d'une éventuelle erreur rencontrée. [OUT]*
+* *
+* Description : Fournit le contenu d'un élément avec une valeur entière. *
+* *
+* Retour : Valeur trouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+long long get_json_integer_value(JsonNode *root, const char *xpath, GError **error)
+{
+ long long result; /* Valeur à retourner */
+ JsonNode *found; /* Accès direct aux trouvailles*/
+ JsonArray *array; /* Liste des résultats */
+ guint count; /* Taille de la liste */
+ JsonNode *node; /* Noeud portant la cible */
+ GValue value; /* Valeur correspondante */
+
+ result = 0xffffffffffffffffll;
+
+ *error = NULL;
+ found = json_path_query(xpath, root, error);
+
+ if (found != NULL)
+ {
+ assert(*error == NULL);
+
+ array = json_node_get_array(found);
+
+ count = json_array_get_length(array);
+
+ if (count == 1)
+ {
+ node = json_array_get_element(array, 0);
+
+ memset(&value, 0, sizeof(GValue));
+ json_node_get_value(node, &value);
+
+ if (G_VALUE_HOLDS(&value, G_TYPE_INT64))
+ result = json_array_get_int_element(array, 0);
+
+ }
+
+ json_node_unref(found);
+
+ }
+
+ return result;
+
+}
diff --git a/src/common/json.h b/src/common/json.h
new file mode 100644
index 0000000..8794bf6
--- /dev/null
+++ b/src/common/json.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * json.h - prototypes pour des manipulations génériques de données au format JSON
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_JSON_H
+#define _COMMON_JSON_H
+
+
+#include <stdbool.h>
+#include <json-glib/json-glib.h>
+
+
+
+/* Détermine la présence d'un élément avec une valeur textuelle. */
+bool has_json_string_value(JsonNode *, const char *, GError **);
+
+/* Fournit le contenu d'un élément avec une valeur textuelle. */
+char *get_json_string_value(JsonNode *, const char *, GError **);
+
+/* Fournit le contenu d'un élément avec une valeur entière. */
+long long get_json_integer_value(JsonNode *, const char *, GError **);
+
+
+
+#endif /* _COMMON_JSON_H */
diff --git a/src/common/leb128.c b/src/common/leb128.c
index c8d2ace..7fae4d0 100644
--- a/src/common/leb128.c
+++ b/src/common/leb128.c
@@ -24,6 +24,20 @@
#include "leb128.h"
+#include <malloc.h>
+
+
+#include "io.h"
+
+
+/**
+ * Quantité maximale d'octets de représentation.
+ *
+ * sizeof([u]leb128_t) / 7 = 9.142857142857142
+ *
+ */
+#define MAX_LEB128_BYTES 9
+
/******************************************************************************
* *
@@ -113,10 +127,63 @@ bool read_leb128(leb128_t *target, const bin_t *data, phys_t *pos, phys_t len)
/******************************************************************************
* *
+* Paramètres : value = valeur à constituer. [OUT] *
+* fd = flux ouvert en lecture à consulter. *
+* *
+* Description : Restaure un nombre non signé encodé au format LEB128. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_uleb128(uleb128_t *value, int fd)
+{
+ bool result; /* Bilan à retourner */
+ unsigned int shift; /* Décalage à appliquer */
+ uint8_t byte; /* Octet à transposer */
+
+ result = false;
+
+ *value = 0;
+
+ shift = 0;
+
+ while (true)
+ {
+ /* Encodage sur trop d'octets ? */
+ if (shift > (7 * MAX_LEB128_BYTES))
+ {
+ result = false;
+ break;
+ }
+
+ result = safe_read(fd, &byte, sizeof(uint8_t));
+ if (!result) break;
+
+ *value |= ((byte & 0x7f) << shift);
+
+ result = true;
+
+ if ((byte & 0x80) == 0x00)
+ break;
+
+ shift += 7;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : value = valeur à consigner. *
-* pbuf = tampon de données à constituer. [OUT] *
+* fd = flux ouvert en écriture. *
* *
-* Description : Encode un nombre non signé encodé au format LEB128. *
+* Description : Sauvegarde un nombre non signé encodé au format LEB128. *
* *
* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
* *
@@ -124,7 +191,7 @@ bool read_leb128(leb128_t *target, const bin_t *data, phys_t *pos, phys_t len)
* *
******************************************************************************/
-bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
+bool store_uleb128(const uleb128_t *value, int fd)
{
bool result; /* Bilan à retourner */
uleb128_t tmp; /* Valeur modifiable */
@@ -140,7 +207,7 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
if (tmp != 0)
byte |= 0x80;
- result = extend_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
+ result = safe_write(fd, &byte, sizeof(uint8_t));
}
while (result && tmp != 0);
@@ -153,9 +220,9 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
/******************************************************************************
* *
* Paramètres : value = valeur à consigner. *
-* pbuf = tampon de données à constituer. [OUT] *
+* len = taille du tampon de données à constitué. [OUT] *
* *
-* Description : Encode un nombre signé encodé au format LEB128. *
+* Description : Encode un nombre non signé encodé au format LEB128. *
* *
* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
* *
@@ -163,19 +230,81 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
* *
******************************************************************************/
-bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
+void *pack_uleb128(const uleb128_t *value, size_t *len)
{
+ uint8_t *result; /* Données à retourner */
+ uleb128_t tmp; /* Valeur modifiable */
+ uint8_t *byte; /* Octet à transposer */
- bool result; /* Bilan à retourner */
+ /* Calcul de la quantité d'octets nécessaires */
+
+ *len = 0;
+
+ tmp = *value;
+
+ do
+ {
+ tmp >>= 7;
+ (*len)++;
+ }
+ while (tmp != 0);
+
+ /* Exportation */
+
+ result = malloc(*len * sizeof(uint8_t));
+ byte = result;
+
+ tmp = *value;
+
+ do
+ {
+ *byte = (tmp & 0x7f);
+ tmp >>= 7;
+
+ if (tmp != 0)
+ *byte |= 0x80;
+
+ byte++;
+
+ }
+ while (tmp != 0);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : value = valeur à consigner. *
+* len = taille du tampon de données à constitué. [OUT] *
+* *
+* Description : Encode un nombre signé encodé au format LEB128. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void *pack_leb128(const leb128_t *value, size_t *len)
+{
+ uint8_t *result; /* Données à retourner */
+ bool negative; /* Nature de la valeur */
uleb128_t tmp; /* Valeur modifiable */
bool more; /* Poursuite des traitements */
- bool negative; /* Nature de la valeur */
uint8_t byte; /* Octet à transposer */
+ uint8_t *iter; /* Boucle de parcours */
+
+ negative = (*value < 0);
+
+ /* Calcul de la quantité d'octets nécessaires */
+
+ *len = 0;
tmp = *value;
more = true;
- negative = (*value < 0);
while (more)
{
@@ -198,10 +327,44 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
if ((tmp == 0 && (byte & 0x40) == 0x00) || (tmp == -1 && (byte & 0x40) == 0x40))
more = false;
+ (*len)++;
+
+ }
+
+ /* Exportation */
+
+ result = malloc(*len * sizeof(uint8_t));
+ iter = result;
+
+ tmp = *value;
+
+ more = true;
+
+ while (more)
+ {
+ *iter = (tmp & 0x7f);
+ tmp >>= 7;
+
+ /**
+ * Propagation forcée du bit de signe pour les implémentations de
+ * décalage basées sur une opération logique et non arithmétique.
+ */
+
+ if (negative)
+ tmp |= (~0llu << (LEB128_BITS_COUNT - 7));
+
+ /**
+ * Le bit de signe n'est pas le bit de poids fort ici :
+ * On travaille sur 7 bits, donc le masque est 0x40 !
+ */
+
+ if ((tmp == 0 && (*iter & 0x40) == 0x00) || (tmp == -1 && (*iter & 0x40) == 0x40))
+ more = false;
+
else
- byte |= 0x80;
+ *iter |= 0x80;
- result = extend_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
+ iter++;
}
@@ -213,7 +376,8 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
/******************************************************************************
* *
* Paramètres : value = valeur à constituer. [OUT] *
-* pbuf = tampon de données à consulter. *
+* pos = tête de lecture à faire évoluer. [OUT] *
+* max = position maximale liée à la fin des données. *
* *
* Description : Décode un nombre non signé encodé au format LEB128. *
* *
@@ -223,38 +387,45 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
* *
******************************************************************************/
-bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)
+bool unpack_uleb128(uleb128_t *value, const void **pos, const void *max)
{
bool result; /* Bilan à retourner */
unsigned int shift; /* Décalage à appliquer */
- uint8_t byte; /* Octet à transposer */
+ uint8_t *byte; /* Octet à transposer */
- result = true;
+ result = false;
*value = 0;
shift = 0;
+ byte = *(uint8_t **)pos;
- while (true)
+ do
{
/* Encodage sur trop d'octets ? */
- if (shift > (7 * sizeof(uleb128_t)))
+ if (shift > (7 * MAX_LEB128_BYTES))
{
result = false;
break;
}
- result = extract_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
- if (!result) break;
+ /* Atteinte de la fin des données ? */
+ if ((void *)byte >= max)
+ {
+ result = false;
+ break;
+ }
- *value |= ((byte & 0x7f) << shift);
+ *value |= ((*byte & 0x7f) << shift);
- if ((byte & 0x80) == 0x00)
- break;
+ result = true;
shift += 7;
}
+ while ((*byte++ & 0x80) == 0x80);
+
+ *pos = byte;
return result;
@@ -264,7 +435,8 @@ bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)
/******************************************************************************
* *
* Paramètres : value = valeur à constituer. [OUT] *
-* pbuf = tampon de données à consulter. *
+* pos = tête de lecture à faire évoluer. [OUT] *
+* max = position maximale liée à la fin des données. *
* *
* Description : Décode un nombre signé encodé au format LEB128. *
* *
@@ -274,44 +446,56 @@ bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)
* *
******************************************************************************/
-bool unpack_leb128(leb128_t *value, packed_buffer_t *pbuf)
+bool unpack_leb128(leb128_t *value, const void **pos, const void *max)
{
bool result; /* Bilan à retourner */
unsigned int shift; /* Décalage à appliquer */
- uint8_t byte; /* Octet à transposer */
+ uint8_t *byte; /* Octet à transposer */
- result = true;
+ result = false;
*value = 0;
shift = 0;
+ byte = *(uint8_t **)pos;
do
{
/* Encodage sur trop d'octets ? */
- if (shift > (7 * sizeof(leb128_t)))
+ if (shift > (7 * MAX_LEB128_BYTES))
{
result = false;
break;
}
- result = extract_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
- if (!result) break;
+ /* Atteinte de la fin des données ? */
+ if ((void *)byte >= max)
+ {
+ result = false;
+ break;
+ }
- *value |= ((byte & 0x7f) << shift);
+ *value |= ((*byte & 0x7f) << shift);
+
+ result = true;
shift += 7;
}
- while ((byte & 0x80) == 0x80);
+ while ((*byte++ & 0x80) == 0x80);
/**
* Le bit de signe n'est pas le bit de poids fort ici :
* On travaille sur 7 bits, donc le masque est 0x40 !
*/
- if (shift < LEB128_BITS_COUNT && (byte & 0x40) == 0x40)
- *value |= (~0llu << shift);
+ if (result)
+ {
+ if (shift < LEB128_BITS_COUNT && (byte[-1] & 0x40) == 0x40)
+ *value |= (~0llu << shift);
+ }
+
+ *pos = byte;
return result;
diff --git a/src/common/leb128.h b/src/common/leb128.h
index f438068..cb712a3 100644
--- a/src/common/leb128.h
+++ b/src/common/leb128.h
@@ -30,7 +30,6 @@
#include "datatypes.h"
-#include "packed.h"
@@ -58,17 +57,23 @@ bool read_uleb128(uleb128_t *, const bin_t *, phys_t *, phys_t);
/* Lit un nombre signé encodé au format LEB128. */
bool read_leb128(leb128_t *, const bin_t *, phys_t *, phys_t);
+/* Charge un nombre non signé encodé au format LEB128. */
+bool load_uleb128(uleb128_t *, int);
+
+/* Sauvegarde un nombre non signé encodé au format LEB128. */
+bool store_uleb128(const uleb128_t *, int);
+
/* Encode un nombre non signé encodé au format LEB128. */
-bool pack_uleb128(const uleb128_t *, packed_buffer_t *);
+void *pack_uleb128(const uleb128_t *, size_t *);
/* Encode un nombre signé encodé au format LEB128. */
-bool pack_leb128(const leb128_t *, packed_buffer_t *);
+void *pack_leb128(const leb128_t *, size_t *);
-/* Décode un nombre non signé encodé au format LEB128. */
-bool unpack_uleb128(uleb128_t *, packed_buffer_t *);
+/* Encode un nombre non signé encodé au format LEB128. */
+bool unpack_uleb128(uleb128_t *, const void **, const void *);
/* Décode un nombre signé encodé au format LEB128. */
-bool unpack_leb128(leb128_t *, packed_buffer_t *);
+bool unpack_leb128(leb128_t *, const void **, const void *);
diff --git a/src/common/pathname.c b/src/common/pathname.c
index dd3ec9e..81dc1e3 100644
--- a/src/common/pathname.c
+++ b/src/common/pathname.c
@@ -33,13 +33,13 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <gio/gio.h>
#include <sys/stat.h>
#include "extstr.h"
#include "io.h"
#include "../core/logs.h"
-//#include "../core/params.h" // TODO : config
@@ -316,16 +316,19 @@ int ensure_path_exists(const char *path)
* Remarques : - *
* *
******************************************************************************/
-#if 0 // TODO
+
int make_tmp_file(const char *prefix, const char *suffix, char **filename)
{
int result; /* Flux ou code à retourner */
- const char *tmpdir; /* Répertoire d'accueil */
- bool status; /* Bilan d'un consultation */
+ GSettings *settings; /* Configuration sollicitée */
+ gchar *tmpdir; /* Répertoire d'accueil */
size_t slen; /* Taille du suffixe */
- status = g_generic_config_get_value(get_main_configuration(), MPK_TMPDIR, &tmpdir);
- if (!status) return -1;
+ /* Récupération d'un répertoire de travail temporaire */
+
+ settings = g_settings_new("re.chrysalide.framework.paths");
+
+ tmpdir = g_settings_get_string(settings, "tmp-work-dir");
slen = strlen(suffix);
@@ -334,6 +337,12 @@ int make_tmp_file(const char *prefix, const char *suffix, char **filename)
else
asprintf(filename, "%s" G_DIR_SEPARATOR_S "%s-%d.XXXXXX", tmpdir, prefix, getpid());
+ g_free(tmpdir);
+
+ g_clear_object(&settings);
+
+ /* Mise en place d'un fichier temporaire */
+
result = ensure_path_exists(*filename);
if (result == 0)
@@ -356,7 +365,7 @@ int make_tmp_file(const char *prefix, const char *suffix, char **filename)
return result;
}
-#endif
+
/******************************************************************************
* *
diff --git a/src/common/pathname.h b/src/common/pathname.h
index 1b6624c..104833b 100644
--- a/src/common/pathname.h
+++ b/src/common/pathname.h
@@ -42,9 +42,7 @@ bool mkpath(const char *);
int ensure_path_exists(const char *);
/* Met en place un fichier temporaire. */
-#if 0 // TODO
int make_tmp_file(const char *, const char *, char **);
-#endif
/* Copie un fichier. */
bool copy_file(const char *, const char *);
diff --git a/src/common/sort.h b/src/common/sort.h
index 39a6f33..27e3739 100644
--- a/src/common/sort.h
+++ b/src/common/sort.h
@@ -37,6 +37,9 @@ int sort_boolean(bool, bool);
/* Compare une valeur avec une autre. */
int sort_unsigned_long(unsigned long, unsigned long);
+#define sort_size(v1, v2) \
+ sort_unsigned_long(v1, v2)
+
/* Compare une valeur avec une autre. */
int sort_signed_long_long(signed long long, signed long long);
diff --git a/src/common/szbin.h b/src/common/szbin.h
new file mode 100644
index 0000000..8524ae3
--- /dev/null
+++ b/src/common/szbin.h
@@ -0,0 +1,282 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * szbin.h - prototypes pour une manipulation de données accompagnées d'une taille
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_SZBIN_H
+#define _COMMON_SZBIN_H
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "datatypes.h"
+#include "io.h"
+#include "leb128.h"
+#include "sort.h"
+
+
+
+/* Structure associant données et taille */
+typedef struct _sized_binary_t
+{
+ union {
+
+ const char *static_data; /* Données non modifiées */
+ char *data; /* Chaîne de caractères */
+
+ const bin_t *static_bin_data; /* Données brutes non modifiées*/
+ bin_t *bin_data; /* Données brutes */
+
+ };
+
+ size_t size; /* Taille correspondante */
+
+} sized_binary_t;
+
+
+#define init_sized_binary(sb) \
+ do \
+ { \
+ (sb)->data = NULL; \
+ (sb)->size = 0; \
+ } \
+ while (0)
+
+
+#define setup_sized_binary(sb, s) \
+ do \
+ { \
+ (sb)->data = malloc(s); \
+ (sb)->size = s; \
+ } \
+ while (0)
+
+
+#define setup_sized_binary_from_static_string(sb, s) \
+ do \
+ { \
+ (sb)->static_data = s; \
+ (sb)->size = strlen(s) + 1; \
+ } \
+ while (0)
+
+
+#define dup_into_sized_binary(sb, d, s) \
+ do \
+ { \
+ size_t __size_once; \
+ __size_once = s; \
+ setup_sized_binary(sb, __size_once);\
+ memcpy((sb)->data, d, __size_once); \
+ } \
+ while (0)
+
+
+#define dup_sized_binary(dst, src) \
+ dup_into_sized_binary((dst), (src)->static_data, (src)->size)
+
+
+#define exit_sized_binary(sb) \
+ do \
+ { \
+ if ((sb)->data != NULL) \
+ { \
+ free((sb)->data); \
+ init_sized_binary(sb); \
+ } \
+ } \
+ while (0)
+
+
+#define resize_sized_binary(sb, s) \
+ do \
+ { \
+ (sb)->size = s; \
+ (sb)->data = realloc((sb)->data, \
+ (sb)->size); \
+ } \
+ while (0)
+
+
+#define add_to_sized_binary(sb, d, s) \
+ do \
+ { \
+ size_t __old_size; \
+ __old_size = (sb)->size; \
+ (sb)->size += s; \
+ (sb)->data = realloc((sb)->data, \
+ (sb)->size); \
+ memcpy((sb)->data + __old_size, \
+ d, s); \
+ } \
+ while (0)
+
+
+#define add_static_to_sized_binary(sb, d) \
+ do \
+ { \
+ size_t __len; \
+ __len = sizeof(d) - 1; \
+ add_to_sized_binary(sb, d, __len); \
+ } \
+ while (0)
+
+
+#define memcmp_sized_binary(s1, s2) \
+ ({ \
+ int __ret; \
+ __ret = sort_size((s1)->size, (s2)->size); \
+ if (__ret == 0) \
+ __ret = memcmp((s1)->data, (s2)->data, (s1)->size); \
+ __ret; \
+ })
+
+
+
+/**
+ * Conservations et rechargements.
+ */
+
+#define load_sized_binary(sb, f) \
+ ({ \
+ uleb128_t __sz; \
+ bool __ret; \
+ __ret = load_uleb128(&__sz, f); \
+ if (__ret) \
+ { \
+ setup_sized_binary(sb, __sz); \
+ __ret = safe_read(f, (sb)->data, (sb)->size); \
+ if (!__ret) \
+ exit_sized_binary(sb); \
+ } \
+ __ret; \
+ })
+
+
+#define load_sized_binary_as_string(sb, f) \
+ ({ \
+ uleb128_t __sz; \
+ bool __ret; \
+ __ret = load_uleb128(&__sz, f); \
+ if (__ret) \
+ { \
+ setup_sized_binary(sb, __sz + 1); \
+ __ret = safe_read(f, (sb)->data, __sz); \
+ if (!__ret) \
+ exit_sized_binary(sb); \
+ (sb)->data[__sz] = '\0'; \
+ } \
+ __ret; \
+ })
+
+
+#define store_sized_binary(sb, f) \
+ ({ \
+ bool __ret; \
+ __ret = store_uleb128((const uleb128_t []){ (sb)->size }, f); \
+ if (__ret) \
+ __ret = safe_write(f, (sb)->static_data, (sb)->size); \
+ __ret; \
+ })
+
+
+#define store_sized_binary_as_string(sb, f) \
+ ({ \
+ bool __ret; \
+ size_t __length; \
+ assert((sb)->size >= 1); \
+ __length = (sb)->size - 1; \
+ assert((sb)->static_data[__length] == '\0'); \
+ __ret = store_uleb128((const uleb128_t []){ __length }, f); \
+ if (__ret) \
+ __ret = safe_write(f, (sb)->static_data, __length); \
+ __ret; \
+ })
+
+
+#define unpack_sized_binary(sb, p, m) \
+ ({ \
+ uleb128_t __sz; \
+ bool __ret; \
+ __ret = unpack_uleb128(&__sz, p, m); \
+ if (__ret) \
+ { \
+ setup_sized_binary(sb, __sz); \
+ memcpy((sb)->data, *p, (sb)->size); \
+ *((uint8_t **)p) += __sz; \
+ } \
+ __ret; \
+ })
+
+
+#define unpack_sized_binary_as_string(sb, p, m) \
+ ({ \
+ uleb128_t __sz; \
+ bool __ret; \
+ __ret = unpack_uleb128(&__sz, p, m); \
+ if (__ret) \
+ { \
+ setup_sized_binary(sb, __sz + 1); \
+ memcpy((sb)->data, *p, __sz); \
+ (sb)->data[__sz] = '\0'; \
+ *((uint8_t **)p) += __sz; \
+ } \
+ __ret; \
+ })
+
+
+#define pack_sized_binary(sb, l) \
+ ({ \
+ uint8_t *__result; \
+ size_t __pos; \
+ __result = pack_uleb128((const uleb128_t []){ (sb)->size }, l); \
+ __pos = *(l); \
+ *(l) += (sb)->size; \
+ __result = realloc(__result, *(l) * sizeof(uint8_t)); \
+ memcpy(&__result[__pos], (sb)->static_data, \
+ ((sb)->size * sizeof(uint8_t))); \
+ __result; \
+ })
+
+
+#define pack_sized_binary_as_string(sb, l) \
+ ({ \
+ uint8_t *__result; \
+ size_t __length; \
+ size_t __pos; \
+ assert((sb)->size >= 1); \
+ __length = (sb)->size - 1; \
+ assert((sb)->static_data[__length] == '\0'); \
+ __result = pack_uleb128((const uleb128_t []){ __length }, l); \
+ __pos = *(l); \
+ *(l) += __length; \
+ __result = realloc(__result, *(l) * sizeof(uint8_t)); \
+ memcpy(&__result[__pos], (sb)->static_data, \
+ (__length * sizeof(uint8_t))); \
+ __result; \
+ })
+
+
+
+#endif /* _COMMON_SZBIN_H */
diff --git a/src/common/szstr.h b/src/common/szstr.h
index 406a9f1..c48d81f 100644
--- a/src/common/szstr.h
+++ b/src/common/szstr.h
@@ -54,7 +54,7 @@ typedef struct _sized_string_t
typedef sized_string_t sized_binary_t;
-
+/*
#define init_szstr(s) \
do \
{ \
@@ -62,6 +62,7 @@ typedef sized_string_t sized_binary_t;
(s)->len = 0; \
} \
while (0)
+*/
#define szstrdup(dst, src) \
do \
@@ -74,6 +75,7 @@ typedef sized_string_t sized_binary_t;
#define copy_szstr(d, s) (d) = (s);
+/*
#define exit_szstr(s) \
do \
{ \
@@ -84,6 +86,7 @@ typedef sized_string_t sized_binary_t;
} \
} \
while (0)
+*/
#define szstrcmp(s1, s2) \
({ \
diff --git a/src/common/xdg.c b/src/common/xdg.c
index cabff75..eb64dad 100644
--- a/src/common/xdg.c
+++ b/src/common/xdg.c
@@ -24,20 +24,41 @@
#include "xdg.h"
-#include <dirent.h>
-#include <errno.h>
+#include <assert.h>
#include <glib.h>
#include <malloc.h>
-#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+
+
+#include "pathname.h"
+
+
+
+/**
+ * Cf. https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ */
+
+/* $HOME/.cache */
+#define CACHE_HOME_SUFFIX ".cache" G_DIR_SEPARATOR_S
+
+/* $HOME/.config */
+#define CONFIG_HOME_SUFFIX ".config" G_DIR_SEPARATOR_S
+
+/* $HOME/.local/share */
+#define DATA_HOME_SUFFIX ".local" G_DIR_SEPARATOR_S "share" G_DIR_SEPARATOR_S
+
+/* $HOME/.local/state */
+#define STATE_HOME_SUFFIX ".local" G_DIR_SEPARATOR_S "state" G_DIR_SEPARATOR_S
/******************************************************************************
* *
* Paramètres : suffix = élément visé dans le répertoire de configuration. *
+* create = assure la mise en place du répertoire final. *
* *
-* Description : Détermine le chemin d'un répertoire selon les specs. XDG. *
+* Description : Détermine le chemin d'un répertoire de données XDG. *
* *
* Retour : Chemin d'accès aux configurations personnelles ou NULL. *
* *
@@ -45,70 +66,321 @@
* *
******************************************************************************/
-char *get_xdg_config_dir(const char *suffix)
+char *get_xdg_cache_dir(const char *suffix, bool create)
{
char *result; /* Chemin d'accès à renvoyer */
const char *env; /* Valeur de l'environnement */
- DIR *directory; /* Répertoire avec contenu ? */
- struct dirent *entry; /* Elément de répertoire */
+ int ret; /* Bilan d'une assurance */
+
+ assert(suffix[0] != G_DIR_SEPARATOR);
result = NULL;
- env = getenv("XDG_CONFIG_HOME");
+ env = getenv("XDG_CACHE_HOME");
if (env != NULL && env[0] != '\0')
{
- directory = opendir(env);
- if (directory == NULL) goto default_cfg_dir;
+ result = calloc(strlen(env) + 1 + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, suffix);
+
+ }
+
+ else
+ {
+ env = getenv("HOME");
+ if (env == NULL || env[0] == '\0') goto no_env;
+
+ result = calloc(strlen(env) + 1 + strlen(CACHE_HOME_SUFFIX) + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, CACHE_HOME_SUFFIX);
+ strcat(result, suffix);
+
+ }
+
+ if (create)
+ {
+ ret = ensure_path_exists(result);
- while (1)
+ if (ret != 0)
{
- errno = 0;
+ free(result);
+ result = NULL;
+ }
- entry = readdir(directory);
+ }
- if (entry == NULL)
- {
- if (errno != 0)
- perror("readdir");
+ no_env:
- break;
+ return result;
+
+}
- }
- if (strcmp(entry->d_name, ".") == 0) continue;
- if (strcmp(entry->d_name, "..") == 0) continue;
+/******************************************************************************
+* *
+* Paramètres : suffix = élément visé dans le répertoire de configuration. *
+* create = assure la mise en place du répertoire final. *
+* *
+* Description : Détermine le chemin d'un répertoire de données XDG. *
+* *
+* Retour : Chemin d'accès aux configurations personnelles ou NULL. *
+* *
+* Remarques : cf. http://standards.freedesktop.org/basedir-spec/. *
+* *
+******************************************************************************/
- result = calloc(strlen(env) + 2 + strlen(suffix) + 1, sizeof(char));
- strcpy(result, env);
+char *get_xdg_config_dir(const char *suffix, bool create)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+ const char *env; /* Valeur de l'environnement */
+ int ret; /* Bilan d'une assurance */
- if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
- strcat(result, G_DIR_SEPARATOR_S);
+ assert(suffix[0] != G_DIR_SEPARATOR);
- strcat(result, ".");
- strcat(result, suffix);
+ result = NULL;
+ env = getenv("XDG_CONFIG_HOME");
+
+ if (env != NULL && env[0] != '\0')
+ {
+ result = calloc(strlen(env) + 1 + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, suffix);
+
+ }
+
+ else
+ {
+ env = getenv("HOME");
+ if (env == NULL || env[0] == '\0') goto no_env;
+
+ result = calloc(strlen(env) + 1 + strlen(CONFIG_HOME_SUFFIX) + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, CONFIG_HOME_SUFFIX);
+ strcat(result, suffix);
+
+ }
+
+ if (create)
+ {
+ ret = ensure_path_exists(result);
+
+ if (ret != 0)
+ {
+ free(result);
+ result = NULL;
}
- closedir(directory);
+ }
+
+ no_env:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : suffix = élément visé dans le répertoire de configuration. *
+* create = assure la mise en place du répertoire final. *
+* *
+* Description : Détermine le chemin d'un répertoire de données XDG. *
+* *
+* Retour : Chemin d'accès aux configurations personnelles ou NULL. *
+* *
+* Remarques : cf. http://standards.freedesktop.org/basedir-spec/. *
+* *
+******************************************************************************/
+
+char *get_xdg_data_dir(const char *suffix, bool create)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+ const char *env; /* Valeur de l'environnement */
+ int ret; /* Bilan d'une assurance */
+
+ assert(suffix[0] != G_DIR_SEPARATOR);
+
+ result = NULL;
+
+ env = getenv("XDG_DATA_HOME");
+
+ if (env != NULL && env[0] != '\0')
+ {
+ result = calloc(strlen(env) + 1 + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, suffix);
+
+ }
+
+ else
+ {
+ env = getenv("HOME");
+ if (env == NULL || env[0] == '\0') goto no_env;
+
+ result = calloc(strlen(env) + 1 + strlen(DATA_HOME_SUFFIX) + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, DATA_HOME_SUFFIX);
+ strcat(result, suffix);
}
- default_cfg_dir:
+ if (create)
+ {
+ ret = ensure_path_exists(result);
+
+ if (ret != 0)
+ {
+ free(result);
+ result = NULL;
+ }
+
+ }
+
+ no_env:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : suffix = élément visé dans le répertoire de configuration. *
+* create = assure la mise en place du répertoire final. *
+* *
+* Description : Détermine le chemin d'un répertoire de données XDG. *
+* *
+* Retour : Chemin d'accès aux configurations personnelles ou NULL. *
+* *
+* Remarques : cf. http://standards.freedesktop.org/basedir-spec/. *
+* *
+******************************************************************************/
+
+char *get_xdg_state_dir(const char *suffix, bool create)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+ const char *env; /* Valeur de l'environnement */
+ int ret; /* Bilan d'une assurance */
+
+ assert(suffix[0] != G_DIR_SEPARATOR);
+
+ result = NULL;
+
+ env = getenv("XDG_STATE_HOME");
+
+ if (env != NULL && env[0] != '\0')
+ {
+ result = calloc(strlen(env) + 1 + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
- if (result == NULL)
+ strcat(result, suffix);
+
+ }
+
+ else
{
env = getenv("HOME");
- if (env == NULL || env[0] == '\0') return NULL;
+ if (env == NULL || env[0] == '\0') goto no_env;
+
+ result = calloc(strlen(env) + 1 + strlen(STATE_HOME_SUFFIX) + strlen(suffix) + 1, sizeof(char));
+
+ strcpy(result, env);
+
+ if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
+ strcat(result, G_DIR_SEPARATOR_S);
+
+ strcat(result, STATE_HOME_SUFFIX);
+ strcat(result, suffix);
+
+ }
+
+ if (create)
+ {
+ ret = ensure_path_exists(result);
+
+ if (ret != 0)
+ {
+ free(result);
+ result = NULL;
+ }
+
+ }
- result = calloc(strlen(env) + 1 + strlen(".config" G_DIR_SEPARATOR_S) + strlen(suffix) + 1, sizeof(char));
+ no_env:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : suffix = élément visé dans le répertoire de configuration. *
+* *
+* Description : Détermine le chemin d'un répertoire éphémère XDG. *
+* *
+* Retour : Chemin d'accès aux configurations personnelles ou NULL. *
+* *
+* Remarques : cf. http://standards.freedesktop.org/basedir-spec/. *
+* *
+******************************************************************************/
+
+char *get_xdg_runtime_dir(const char *suffix)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+ const char *env; /* Valeur de l'environnement */
+
+ assert(suffix[0] != G_DIR_SEPARATOR);
+
+ result = NULL;
+
+ env = getenv("XDG_RUNTIME_DIR");
+
+ if (env != NULL && env[0] != '\0')
+ {
+ result = calloc(strlen(env) + 1 + strlen(suffix) + 1, sizeof(char));
strcpy(result, env);
if (env[strlen(env) - 1] != G_DIR_SEPARATOR)
strcat(result, G_DIR_SEPARATOR_S);
- strcat(result, ".config" G_DIR_SEPARATOR_S);
strcat(result, suffix);
}
diff --git a/src/common/xdg.h b/src/common/xdg.h
index c9c2327..a6cd91d 100644
--- a/src/common/xdg.h
+++ b/src/common/xdg.h
@@ -25,9 +25,24 @@
#define _COMMON_XDG_H
+#include <stdbool.h>
-/* Détermine le chemin d'un répertoire selon les specs. XDG. */
-char *get_xdg_config_dir(const char *);
+
+
+/* Détermine le chemin d'un répertoire de données XDG. */
+char *get_xdg_cache_dir(const char *, bool);
+
+/* Détermine le chemin d'un répertoire de données XDG. */
+char *get_xdg_config_dir(const char *, bool);
+
+/* Détermine le chemin d'un répertoire de données XDG. */
+char *get_xdg_data_dir(const char *, bool);
+
+/* Détermine le chemin d'un répertoire de données XDG. */
+char *get_xdg_state_dir(const char *, bool);
+
+/* Détermine le chemin d'un répertoire éphémère XDG. */
+char *get_xdg_runtime_dir(const char *);
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 5bcb13a..15ed866 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -4,11 +4,8 @@ noinst_LTLIBRARIES = libcore4.la # libcore.la
libcore_la_SOURCES = \
collections.h collections.c \
columns.h \
- core.h core.c \
demanglers.h demanglers.c \
- global.h global.c \
logs.h logs.c \
- nproc.h nproc.c \
params.h params.c \
paths.h paths.c \
processors.h processors.c \
@@ -18,10 +15,15 @@ libcore_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
libcore4_la_SOURCES = \
+ core.h core.c \
+ global.h global.c \
logs.h logs.c \
- paths.h paths.c
+ nox.h nox.c \
+ nproc.h nproc.c \
+ paths.h paths.c \
+ processors.h processors.c
-libcore4_la_CFLAGS = $(TOOLKIT_CFLAGS)
+libcore4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
diff --git a/src/core/core.c b/src/core/core.c
index f67e23d..c730fad 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* core.c - chargement et le déchargement du tronc commun
*
- * Copyright (C) 2014-2019 Cyrille Bagard
+ * Copyright (C) 2014-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,6 +24,97 @@
#include "core.h"
+#include "global.h"
+#include "processors.h"
+
+
+
+/* Statuts de chargement */
+static AvailableCoreComponent __loaded = ACC_NONE;
+
+
+
+/******************************************************************************
+* *
+* Paramètres : flags = liste d'éléments à charger. *
+* *
+* Description : Charge une sélection d'éléments de base du programme. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_core_components(AvailableCoreComponent flags)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if ((flags & ACC_GLOBAL_VARS) != 0 && (__loaded & ACC_GLOBAL_VARS) == 0)
+ {
+ set_secret_storage(g_secret_storage_new(NULL));
+
+ set_work_queue(g_work_queue_new());
+
+ __loaded |= ACC_GLOBAL_VARS;
+
+ }
+
+ if ((flags & ACC_CODE_ANALYSIS) != 0 && (__loaded & ACC_CODE_ANALYSIS) == 0)
+ {
+ register_arch_gtypes();
+
+ init_operands_factory();
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : flags = liste d'éléments à décharger. *
+* *
+* Description : Décharge une sélection d'éléments de base du programme. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unload_core_components(AvailableCoreComponent flags)
+{
+ if ((flags & ACC_CODE_ANALYSIS) != 0 && (__loaded & ACC_CODE_ANALYSIS) == 0)
+ {
+ exit_operands_factory();
+
+ }
+
+ if ((flags & ACC_GLOBAL_VARS) != 0 && (__loaded & ACC_GLOBAL_VARS) == 0)
+ {
+ set_work_queue(NULL);
+
+ set_secret_storage(NULL);
+
+ __loaded &= ~ACC_GLOBAL_VARS;
+
+ }
+
+}
+
+
+
+
+
+
+
+#if 0
+
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
@@ -35,7 +126,6 @@
#include "demanglers.h"
#include "global.h"
#include "params.h"
-#include "processors.h"
#include "queue.h"
#include "../analysis/scan/core.h"
#ifdef INCLUDE_MAGIC_SUPPORT
@@ -119,9 +209,6 @@ bool load_all_core_components(bool cs)
if (result) result = init_segment_content_hash_table();
- register_arch_gtypes();
- init_operands_factory();
-
}
}
@@ -147,8 +234,6 @@ void unload_all_core_components(bool cs)
{
if (cs)
{
- exit_operands_factory();
-
exit_segment_content_hash_table();
unload_demanglers_definitions();
@@ -255,3 +340,5 @@ void unload_core_components(AvailableCoreComponent flags)
}
}
+
+#endif
diff --git a/src/core/core.h b/src/core/core.h
index def2813..640476a 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* core.h - prototypes pour le chargement et le déchargement du tronc commun
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,17 +29,15 @@
-/* Charge les éléments de base du programme. */
-bool load_all_core_components(bool);
-
-/* Décharge les éléments de base du programme. */
-void unload_all_core_components(bool);
-
-
/* Eléments à (dé)charger disponibles */
typedef enum _AvailableCoreComponent
{
- ACC_SCAN_FEATURES = (1 << 0), /* Espace de noms pour scan */
+ ACC_NONE = (0 << 0), /* Statut initial */
+ ACC_GLOBAL_VARS = (1 << 0), /* Singletons globaux */
+ ACC_CODE_ANALYSIS = (1 << 1), /* Désassemblage de code */
+ ACC_SCAN_FEATURES = (1 << 2), /* Espace de noms pour scan */
+
+ ACC_ALL_COMPONENTS = (1 << 3) - 1
} AvailableCoreComponent;
diff --git a/src/core/global.c b/src/core/global.c
index c99d711..0275e09 100644
--- a/src/core/global.c
+++ b/src/core/global.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* global.c - conservation et accès aux variables globales
*
- * Copyright (C) 2017-2019 Cyrille Bagard
+ * Copyright (C) 2017-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,38 +24,29 @@
#include "global.h"
-#include <assert.h>
+#include "../glibext/helpers.h"
-/* Mode de fonctionnement */
-static bool _batch_mode = false;
+/* Décompte des émissions et réceptions */
+static GMutex _network_mutex;
+static size_t _bytes_received = 0;
+static size_t _bytes_sent = 0;
/* Gestionnaire de tâches parallèles */
static GWorkQueue *_queue = NULL;
-/* Explorateur de contenus */
-static GContentExplorer *_explorer = NULL;
-
-/* Résolveur de contenus */
-static GContentResolver *_resolver = NULL;
-
-/* Espace de noms racine pour ROST */
-static GScanNamespace *_rost_root_ns = NULL;
-
-/* Projet global actif */
-static GStudyProject *_project = NULL;
-
-/* Avertisseur de changement de projet principal */
-static current_project_change_cb _project_notify = NULL;
+/* Gardien des secrets avec support des stockages */
+static GSecretStorage *_storage = NULL;
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : received = quantité d'octets reçus jusqu'à présent. [OUT] *
+* sent = quantité d'octets émis jusqu'à présent. [OUT] *
* *
-* Description : Note un mode d'exécution sans interface. *
+* Description : Fournit les volumes d'octets échangés sur le réseau. *
* *
* Retour : - *
* *
@@ -63,28 +54,39 @@ static current_project_change_cb _project_notify = NULL;
* *
******************************************************************************/
-void set_batch_mode(void)
+void get_network_stats(size_t *received, size_t *sent)
{
- _batch_mode = true;
+ g_mutex_lock(&_network_mutex);
+
+ *received = _bytes_received;
+ *sent = _bytes_sent;
+
+ g_mutex_unlock(&_network_mutex);
}
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : received = quantité d'octets reçus supplémentaire. *
+* sent = quantité d'octets émis supplémentaire. *
* *
-* Description : Indique le mode d'exécution courant du programme. *
+* Description : Augmente les volumes d'octets échangés sur le réseau. *
* *
-* Retour : true si le fonctionnement est sans interface. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool is_batch_mode(void)
+void update_network_stats(size_t received, size_t sent)
{
- return _batch_mode;
+ g_mutex_lock(&_network_mutex);
+
+ _bytes_received += received;
+ _bytes_sent += sent;
+
+ g_mutex_unlock(&_network_mutex);
}
@@ -101,9 +103,10 @@ bool is_batch_mode(void)
* *
******************************************************************************/
-void set_work_queue(GWorkQueue *queue)
+void set_work_queue(/* __steal */GWorkQueue *queue)
{
- assert(_queue == NULL);
+ if (_queue != NULL)
+ unref_object(_queue);
_queue = queue;
@@ -124,6 +127,8 @@ void set_work_queue(GWorkQueue *queue)
GWorkQueue *get_work_queue(void)
{
+ ref_object(_queue);
+
return _queue;
}
@@ -131,6 +136,131 @@ GWorkQueue *get_work_queue(void)
/******************************************************************************
* *
+* Paramètres : queue = nouveau stockage sécurisé à mémoriser ou NULL. *
+* *
+* Description : Définit le stockage sécurisé principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_secret_storage(/* __steal */GSecretStorage *storage)
+{
+ if (_storage != NULL)
+ unref_object(_storage);
+
+ _storage = storage;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit le stockage sécurisé principal. *
+* *
+* Retour : Gestionnaire de traitements parallèles courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSecretStorage *get_secret_storage(void)
+{
+ ref_object(_storage);
+
+ return _storage;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+#include <assert.h>
+
+
+
+/* Mode de fonctionnement */
+static bool _batch_mode = false;
+
+/* Gestionnaire de tâches parallèles */
+//static GWorkQueue *_queue = NULL;
+
+/* Explorateur de contenus */
+static GContentExplorer *_explorer = NULL;
+
+/* Résolveur de contenus */
+static GContentResolver *_resolver = NULL;
+
+/* Espace de noms racine pour ROST */
+static GScanNamespace *_rost_root_ns = NULL;
+
+/* Projet global actif */
+static GStudyProject *_project = NULL;
+
+/* Avertisseur de changement de projet principal */
+static current_project_change_cb _project_notify = NULL;
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Note un mode d'exécution sans interface. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_batch_mode(void)
+{
+ _batch_mode = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Indique le mode d'exécution courant du programme. *
+* *
+* Retour : true si le fonctionnement est sans interface. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool is_batch_mode(void)
+{
+ return _batch_mode;
+
+}
+
+
+
+
+/******************************************************************************
+* *
* Paramètres : explorer = éventuelle adresse du nouveau gestionnaire. *
* *
* Description : Définit l'adresse de l'explorateur de contenus courant. *
@@ -343,3 +473,5 @@ void register_project_change_notification(current_project_change_cb notify)
_project_notify = notify;
}
+
+#endif
diff --git a/src/core/global.h b/src/core/global.h
index 0a9172b..f5d8a62 100644
--- a/src/core/global.h
+++ b/src/core/global.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* global.h - prototypes pour la conservation et l'accès aux variables globales
*
- * Copyright (C) 2017-2018 Cyrille Bagard
+ * Copyright (C) 2017-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,6 +25,35 @@
#define _CORE_GLOBAL_H
+#include "../glibext/secstorage.h"
+#include "../glibext/workqueue.h"
+
+
+
+/* Fournit les volumes d'octets échangés sur le réseau. */
+void get_network_stats(size_t *, size_t *);
+
+/* Augmente les volumes d'octets échangés sur le réseau. */
+void update_network_stats(size_t, size_t);
+
+/* Définit le gestionnaire de traitements parallèles courant. */
+void set_work_queue(/* __steal */GWorkQueue *);
+
+/* Fournit le gestionnaire de traitements parallèles courant. */
+GWorkQueue *get_work_queue(void);
+
+/* Définit le stockage sécurisé principal. */
+void set_secret_storage(/* __steal */GSecretStorage *);
+
+/* Fournit le stockage sécurisé principal. */
+GSecretStorage *get_secret_storage(void);
+
+
+
+
+
+#if 0
+
#include <stdbool.h>
@@ -42,10 +71,10 @@ void set_batch_mode(void);
bool is_batch_mode(void);
/* Définit le gestionnaire de traitements parallèles courant. */
-void set_work_queue(GWorkQueue *);
+//void set_work_queue(GWorkQueue *);
/* Fournit le gestionnaire de traitements parallèles courant. */
-GWorkQueue *get_work_queue(void);
+//GWorkQueue *get_work_queue(void);
/* Définit l'adresse de l'explorateur de contenus courant. */
void set_current_content_explorer(GContentExplorer *);
@@ -78,5 +107,8 @@ typedef void (* current_project_change_cb) (GStudyProject *, bool);
void register_project_change_notification(current_project_change_cb);
+#endif
+
+
#endif /* _CORE_GLOBAL_H */
diff --git a/src/core/logs.h b/src/core/logs.h
index e8df8bd..3719c6b 100644
--- a/src/core/logs.h
+++ b/src/core/logs.h
@@ -162,6 +162,15 @@ void log_variadic_message(LogMessageType, const char *, ...);
} \
while (0)
+#define LOG_ERROR_ZIP(func, err) \
+ do \
+ { \
+ const char *__msg; \
+ __msg = zip_error_strerror(err); \
+ log_variadic_message(LMT_EXT_ERROR, "[%s:%u] %s: %s", __FUNCTION__, __LINE__, func, __msg); \
+ } \
+ while (0)
+
#endif /* _CORE_LOGS_H */
diff --git a/src/core/nox.c b/src/core/nox.c
new file mode 100644
index 0000000..ccf9de2
--- /dev/null
+++ b/src/core/nox.c
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * nox.c - indication de présence ou d'absence de support graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "nox.h"
+
+
+#include <stddef.h>
+
+
+#include "../common/compiler.h"
+
+
+
+/* Indique la présence ou l'absence d'un affichage graphique. */
+__weak bool _run_in_nox_mode(void);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Indique la présence ou l'absence d'un affichage graphique. *
+* *
+* Retour : Statut à transmettre. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool run_in_nox_mode(void)
+{
+ bool result; /* Statut à retournr */
+
+ if (_run_in_nox_mode == NULL)
+ result = true;
+ else
+ result = _run_in_nox_mode();
+
+ return result;
+
+}
diff --git a/src/core/nox.h b/src/core/nox.h
new file mode 100644
index 0000000..c2c225d
--- /dev/null
+++ b/src/core/nox.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * nox.h - prototypes pour l'indication de présence ou d'absence de support graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _CORE_NOX_H
+#define _CORE_NOX_H
+
+
+#include <stdbool.h>
+
+
+
+/* Indique la présence ou l'absence d'un affichage graphique. */
+bool run_in_nox_mode(void);
+
+
+
+#endif /* _CORE_NOX_H */
diff --git a/src/core/processors.c b/src/core/processors.c
index e4a558f..056fc23 100644
--- a/src/core/processors.c
+++ b/src/core/processors.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* processors.c - enregistrement et fourniture des architectures supportées
*
- * Copyright (C) 2015-2020 Cyrille Bagard
+ * Copyright (C) 2015-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,13 +29,13 @@
#include <pthread.h>
#include <string.h>
-
+#if 0
#include "../arch/instructions/raw.h"
#include "../arch/instructions/undefined.h"
#include "../arch/operands/immediate.h"
#include "../arch/operands/register.h"
#include "../arch/operands/target.h"
-
+#endif
/* Cache des singletons d'opérandes */
@@ -77,12 +77,12 @@ static proc_t *find_processor_by_key(const char *);
void register_arch_gtypes(void)
{
- g_type_ensure(G_TYPE_RAW_INSTRUCTION);
- g_type_ensure(G_TYPE_UNDEF_INSTRUCTION);
+ //g_type_ensure(G_TYPE_RAW_INSTRUCTION);
+ //g_type_ensure(G_TYPE_UNDEF_INSTRUCTION);
- g_type_ensure(G_TYPE_IMM_OPERAND);
- g_type_ensure(G_TYPE_REGISTER_OPERAND);
- g_type_ensure(G_TYPE_TARGET_OPERAND);
+ //g_type_ensure(G_TYPE_IMM_OPERAND);
+ //g_type_ensure(G_TYPE_REGISTER_OPERAND);
+ //g_type_ensure(G_TYPE_TARGET_OPERAND);
}
@@ -126,7 +126,7 @@ GSingletonFactory *get_operands_factory(void)
result = __operands_factory;
- g_object_ref(G_OBJECT(result));
+ ref_object(result);
return result;
@@ -154,7 +154,7 @@ void exit_operands_factory(void)
}
-
+#if 0
/******************************************************************************
* *
* Paramètres : type = type GLib représentant le type à instancier. *
@@ -206,7 +206,7 @@ bool register_processor_type(GType type)
done:
- g_object_unref(G_OBJECT(proc));
+ unref_object(proc);
return result;
@@ -341,3 +341,4 @@ GArchProcessor *get_arch_processor_for_key(const char *key)
return result;
}
+#endif
diff --git a/src/core/processors.h b/src/core/processors.h
index 6aa2d1e..b622305 100644
--- a/src/core/processors.h
+++ b/src/core/processors.h
@@ -29,7 +29,7 @@
#include <stdbool.h>
-#include "../arch/processor.h"
+//#include "../arch/processor.h"
#include "../glibext/singleton.h"
@@ -45,7 +45,7 @@ GSingletonFactory *get_operands_factory(void);
/* Supprime le fournisseur d'instances uniques d'opérandes. */
void exit_operands_factory(void);
-
+#if 0
/* Enregistre un processeur pour une architecture donnée. */
bool register_processor_type(GType);
@@ -57,7 +57,7 @@ char **get_all_processor_keys(size_t *);
/* Fournit le processeur d'architecture correspondant à un nom. */
GArchProcessor *get_arch_processor_for_key(const char *);
-
+#endif
#endif /* _CORE_PROCESSORS_H */
diff --git a/src/data/Makefile.am b/src/data/Makefile.am
new file mode 100644
index 0000000..8cbe67a
--- /dev/null
+++ b/src/data/Makefile.am
@@ -0,0 +1,2 @@
+
+SUBDIRS = images
diff --git a/src/data/images/Makefile.am b/src/data/images/Makefile.am
new file mode 100644
index 0000000..d5ec84f
--- /dev/null
+++ b/src/data/images/Makefile.am
@@ -0,0 +1,33 @@
+
+BUILT_SOURCES = resources.h resources.c
+
+noinst_LTLIBRARIES = libdataimages.la
+
+RES_FILES = \
+ about-bg.png \
+ dock-station-left-symbolic.svg \
+ dock-station-right-symbolic.svg \
+ dock-station-bottom-symbolic.svg \
+ logs-symbolic.svg
+
+libdataimages_la_SOURCES = \
+ resources.h resources.c
+
+libdataimages_la_CFLAGS = $(LIBGIOUNIX_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libdataimages_la_SOURCES:%c=)
+
+
+resources.c: gresource.xml $(RES_FILES)
+ glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name data_images gresource.xml
+
+resources.h: gresource.xml
+ glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name data_images gresource.xml
+
+
+CLEANFILES = resources.h resources.c
+
+EXTRA_DIST = gresource.xml $(RES_FILES)
diff --git a/src/data/images/dock-station-bottom-symbolic.svg b/src/data/images/dock-station-bottom-symbolic.svg
new file mode 100644
index 0000000..37084ac
--- /dev/null
+++ b/src/data/images/dock-station-bottom-symbolic.svg
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dock-station-bottom-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="4.2708118"
+ inkscape:cx="87.219952"
+ inkscape:cy="89.444353"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g3929" />
+ <defs
+ id="defs2">
+ <clipPath
+ id="k">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1320" />
+ </clipPath>
+ <mask
+ id="j">
+ <g
+ filter="url(#a)"
+ id="g1317">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1315" />
+ </g>
+ </mask>
+ <filter
+ id="a"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix1280" />
+ </filter>
+ <clipPath
+ id="i">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1312" />
+ </clipPath>
+ <mask
+ id="h">
+ <g
+ filter="url(#a)"
+ id="g1309">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1307" />
+ </g>
+ </mask>
+ <filter
+ id="filter3652"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3650" />
+ </filter>
+ <clipPath
+ id="g">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1304" />
+ </clipPath>
+ <mask
+ id="f">
+ <g
+ filter="url(#a)"
+ id="g1301">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1299" />
+ </g>
+ </mask>
+ <filter
+ id="filter3661"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3659" />
+ </filter>
+ <clipPath
+ id="e">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1296" />
+ </clipPath>
+ <mask
+ id="d">
+ <g
+ filter="url(#a)"
+ id="g1293">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.35"
+ id="path1291" />
+ </g>
+ </mask>
+ <filter
+ id="filter3670"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3668" />
+ </filter>
+ <clipPath
+ id="c">
+ <path
+ d="M 0,0 H 800 V 800 H 0 Z"
+ id="path1288" />
+ </clipPath>
+ <mask
+ id="b">
+ <g
+ filter="url(#a)"
+ id="g1285">
+ <path
+ d="M 0,0 H 16 V 16 H 0 Z"
+ fill-opacity="0.3"
+ id="path1283" />
+ </g>
+ </mask>
+ <filter
+ id="filter3679"
+ height="1"
+ width="1"
+ x="0"
+ y="0">
+ <feColorMatrix
+ in="SourceGraphic"
+ type="matrix"
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ id="feColorMatrix3677" />
+ </filter>
+ </defs>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="g3929">
+ <path
+ id="rect3921"
+ style="fill:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke;fill-opacity:1"
+ d="M 30 15 C 13.380034 15 0 28.380034 0 45 L 0 100 L 0 110 L 0 135 C 0 151.61996 13.380034 165 30 165 L 150 165 C 166.61996 165 180 151.61996 180 135 L 180 110 L 180 100 L 180 45 C 180 28.380034 166.61996 15 150 15 L 30 15 z M 35 35 L 145 35 C 153.30998 35 160 41.690016 160 50 L 160 100 L 20 100 L 20 50 C 20 41.690016 26.690016 35 35 35 z M 20 110 L 160 110 L 160 130 C 160 138.30998 153.30998 145 145 145 L 35 145 C 26.690016 145 20 138.30998 20 130 L 20 110 z " />
+ <path
+ id="rect3923"
+ style="fill:#000000;fill-opacity:0.41999999;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 20 110 L 20 130 C 20 138.30999 26.690008 145 35 145 L 145 145 C 153.30999 145 160 138.30999 160 130 L 160 110 L 20 110 z " />
+ </g>
+</svg>
diff --git a/src/data/images/dock-station-left-symbolic.svg b/src/data/images/dock-station-left-symbolic.svg
new file mode 100644
index 0000000..0f90e8f
--- /dev/null
+++ b/src/data/images/dock-station-left-symbolic.svg
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dock-station-left-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="4.4555556"
+ inkscape:cx="88.541146"
+ inkscape:cy="89.999999"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ id="rect254"
+ style="fill:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke;fill-opacity:1"
+ d="M 30 15 C 13.380034 15 0 28.380034 0 45 L 0 135 C 0 151.61996 13.380034 165 30 165 L 65 165 L 75 165 L 150 165 C 166.61996 165 180 151.61996 180 135 L 180 45 C 180 28.380034 166.61996 15 150 15 L 75 15 L 65 15 L 30 15 z M 35 35 L 65 35 L 65 145 L 35 145 C 26.690016 145 20 138.30998 20 130 L 20 50 C 20 41.690016 26.690016 35 35 35 z M 75 35 L 145 35 C 153.30998 35 160 41.690016 160 50 L 160 130 C 160 138.30998 153.30998 145 145 145 L 75 145 L 75 35 z " />
+ <path
+ id="rect390"
+ style="fill:#000000;fill-opacity:0.41999999;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 35 35 C 26.690008 35 20 41.690008 20 50 L 20 130 C 20 138.30999 26.690008 145 35 145 L 65 145 L 65 35 L 35 35 z " />
+ </g>
+</svg>
diff --git a/src/data/images/dock-station-right-symbolic.svg b/src/data/images/dock-station-right-symbolic.svg
new file mode 100644
index 0000000..774476a
--- /dev/null
+++ b/src/data/images/dock-station-right-symbolic.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dock-station-right-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="4.4555556"
+ inkscape:cx="86.408977"
+ inkscape:cy="89.999999"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ id="rect254"
+ style="fill:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke;fill-opacity:1"
+ d="M 30 15 C 13.380034 15 0 28.380034 0 45 L 0 135 C 0 151.61996 13.380034 165 30 165 L 105 165 L 115 165 L 150 165 C 166.61996 165 180 151.61996 180 135 L 180 45 C 180 28.380034 166.61996 15 150 15 L 115 15 L 105 15 L 30 15 z M 35 35 L 105 35 L 105 145 L 35 145 C 26.690016 145 20 138.30998 20 130 L 20 50 C 20 41.690016 26.690016 35 35 35 z M 115 35 L 145 35 C 153.30998 35 160 41.690016 160 50 L 160 130 C 160 138.30998 153.30998 145 145 145 L 115 145 L 115 35 z " />
+ <path
+ id="rect390"
+ style="fill:#000000;fill-opacity:0.41999999;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 115 35 L 115 145 L 145 145 C 153.30999 145 160 138.30999 160 130 L 160 50 C 160 41.690008 153.30999 35 145 35 L 115 35 z " />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Calque 2"
+ style="display:none;opacity:0.700936">
+ <g
+ fill="#2e3436"
+ id="g182"
+ transform="matrix(11.328515,0,0,10.683311,-1.25624,4.6587097)"
+ style="stroke-width:0.0908993">
+ <path
+ d="m 6.5,13.988281 v -12 h -5 v 12 z m 0,0"
+ fill-opacity="0.35"
+ id="path176"
+ style="stroke-width:0.00826268" />
+ <path
+ d="m 3,0.988281 c -1.644531,0 -3,1.355469 -3,3 v 8 c 0,1.644531 1.355469,3 3,3 h 10 c 1.644531,0 3,-1.355469 3,-3 v -8 c 0,-1.644531 -1.355469,-3 -3,-3 z m 0,2 h 10 c 0.570312,0 1,0.429688 1,1 v 8 c 0,0.570313 -0.429688,1 -1,1 H 3 c -0.570312,0 -1,-0.429687 -1,-1 v -8 c 0,-0.570312 0.429688,-1 1,-1 z m 0,0"
+ id="path178"
+ style="stroke-width:0.0908993" />
+ <path
+ d="m 6,1.988281 h 1 v 12 H 6 Z m 0,0"
+ id="path180"
+ style="stroke-width:0.0908993" />
+ </g>
+ </g>
+</svg>
diff --git a/src/data/images/gresource.xml b/src/data/images/gresource.xml
new file mode 100644
index 0000000..25c8274
--- /dev/null
+++ b/src/data/images/gresource.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/re/chrysalide/framework/gui/dialogs/about">
+ <file compressed="true" alias="bg.png">about-bg.png</file>
+ </gresource>
+ <gresource prefix="/re/chrysalide/framework/gui/icons/scalable/actions">
+ <file compressed="true">dock-station-left-symbolic.svg</file>
+ <file compressed="true">dock-station-right-symbolic.svg</file>
+ <file compressed="true">dock-station-bottom-symbolic.svg</file>
+ <file compressed="true">logs-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/src/data/images/logs-symbolic.svg b/src/data/images/logs-symbolic.svg
new file mode 100644
index 0000000..f541607
--- /dev/null
+++ b/src/data/images/logs-symbolic.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="logs-symbolic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="3.9657403"
+ inkscape:cx="110.44596"
+ inkscape:cy="77.413036"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="fill:#25ff4c;fill-opacity:1">
+ <path
+ id="rect495"
+ style="opacity:1;fill:#000000;fill-opacity:1;stroke-width:1.99999;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ d="M 45 0 C 31.150014 0 20 11.150014 20 25 L 20 155 C 20 168.84999 31.150014 180 45 180 L 155 180 C 168.84999 180 180 168.84999 180 155 L 180 25 C 180 11.150014 168.84999 0 155 0 L 45 0 z M 55 10 L 145 10 C 158.84999 10 170 21.150014 170 35 L 170 145 C 170 158.84999 158.84999 170 145 170 L 55 170 C 41.150014 170 30 158.84999 30 145 L 30 35 C 30 21.150014 41.150014 10 55 10 z " />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect3619"
+ width="75"
+ height="12"
+ x="62.5"
+ y="84"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5029"
+ width="75"
+ height="12"
+ x="62.5"
+ y="127"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5031"
+ width="75"
+ height="12"
+ x="62.5"
+ y="41"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5049"
+ width="34"
+ height="12"
+ x="8.2744884"
+ y="41"
+ rx="6"
+ ry="6" />
+ <rect
+ style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke"
+ id="rect5051"
+ width="34"
+ height="12"
+ x="8.2744884"
+ y="127"
+ rx="6"
+ ry="6" />
+ </g>
+</svg>
diff --git a/src/format/Makefile.am b/src/format/Makefile.am
index 305cd92..3ffe24e 100644
--- a/src/format/Makefile.am
+++ b/src/format/Makefile.am
@@ -1,23 +1,25 @@
noinst_LTLIBRARIES = libformat.la
+# debuggable-int.h \
+# debuggable.h debuggable.c \
+# executable-int.c \
+# preload-int.h \
+# preload.h preload.c \
+# strsym.h strsym.c \
+# symiter.h symiter.c \
+# symbol-int.h \
+# symbol.h symbol.c
+
libformat_la_SOURCES = \
- debuggable-int.h \
- debuggable.h debuggable.c \
- executable-int.h executable-int.c \
+ executable-int.h \
executable.h executable.c \
flat-int.h \
flat.h flat.c \
- format-int.h \
- format.h format.c \
known-int.h \
known.h known.c \
- preload-int.h \
- preload.h preload.c \
- strsym.h strsym.c \
- symiter.h symiter.c \
- symbol-int.h \
- symbol.h symbol.c
+ program-int.h \
+ program.h program.c
libformat_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/format/executable-int.c b/src/format/executable-int.c
deleted file mode 100644
index 0e94e74..0000000
--- a/src/format/executable-int.c
+++ /dev/null
@@ -1,155 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * executable-int.c - code utile aux formats d'exécutables
- *
- * Copyright (C) 2015-2018 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "executable-int.h"
-
-
-
-/******************************************************************************
-* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* off = position physique à retrouver. *
-* pos = position correspondante. [OUT] *
-* *
-* Description : Fournit l'emplacement correspondant à une position physique. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *format, phys_t off, vmpa2t *pos)
-{
- init_vmpa(pos, off, VMPA_NO_VIRTUAL);
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* addr = adresse virtuelle à retrouver. *
-* pos = position correspondante. [OUT] *
-* *
-* Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_exe_format_without_virt_translate_address_into_vmpa(const GExeFormat *format, virt_t addr, vmpa2t *pos)
-{
- /**
- * S'il n'y a pas de notion de mémoire virtuelle, positions physiques et
- * adresses virtuelles se confondent.
- *
- * On reste néanmoins cohérent, et on n'utilise donc pas d'adresse virtuelle.
- *
- * Les sauts dans le code renvoient de façon transparente vers des positions
- * physiques.
- */
-
- init_vmpa(pos, addr, VMPA_NO_VIRTUAL);
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* off = position physique à retrouver. *
-* pos = position correspondante. [OUT] *
-* *
-* Description : Fournit l'emplacement correspondant à une position physique. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_exe_format_translate_offset_into_vmpa_using_portions(GExeFormat *format, phys_t off, vmpa2t *pos)
-{
- bool result; /* Bilan à retourner */
- GBinPortion *portions; /* Liste de découpages */
-
- portions = g_exe_format_get_portions(format);
-
- if (portions == NULL)
- result = false;
-
- else
- {
- result = g_binary_portion_translate_offset_into_vmpa(portions, off, pos);
-
- g_object_unref(G_OBJECT(portions));
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* addr = adresse virtuelle à retrouver. *
-* pos = position correspondante. [OUT] *
-* *
-* Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_exe_format_translate_address_into_vmpa_using_portions(GExeFormat *format, virt_t addr, vmpa2t *pos)
-{
- bool result; /* Bilan à retourner */
- GBinPortion *portions; /* Liste de découpages */
-
- portions = g_exe_format_get_portions(format);
-
- if (portions == NULL)
- result = false;
-
- else
- {
- result = g_binary_portion_translate_address_into_vmpa(portions, addr, pos);
-
- g_object_unref(G_OBJECT(portions));
-
- }
-
- return result;
-
-}
diff --git a/src/format/executable-int.h b/src/format/executable-int.h
index 8722795..1ca1bdb 100644
--- a/src/format/executable-int.h
+++ b/src/format/executable-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* executable-int.h - prototypes de code utile aux formats d'exécutables
*
- * Copyright (C) 2009-2019 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,79 +28,65 @@
#include "executable.h"
-#include "format-int.h"
+#include "program-int.h"
/* Indique le type d'architecture visée par le format. */
-typedef const char * (* get_target_machine_fc) (const GExeFormat *);
+typedef char * (* get_target_machine_fc) (const GExecutableFormat *);
/* Fournit l'adresse principale associée à un format. */
-typedef bool (* get_main_addr_fc) (GExeFormat *, vmpa2t *);
+typedef bool (* get_main_addr_fc) (GExecutableFormat *, vmpa2t *);
/* Etend la définition des portions au sein d'un binaire. */
-typedef void (* refine_portions_fc) (GExeFormat *);
+typedef bool (* refine_portions_fc) (GExecutableFormat *);
/* Fournit l'emplacement correspondant à une position physique. */
-typedef bool (* translate_phys_fc) (GExeFormat *, phys_t, vmpa2t *);
+typedef bool (* translate_phys_fc) (GExecutableFormat *, phys_t, vmpa2t *);
/* Fournit l'emplacement correspondant à une adresse virtuelle. */
-typedef bool (* translate_virt_fc) (GExeFormat *, virt_t, vmpa2t *);
-
-/* Fournit l'emplacement d'une section donnée. */
-typedef bool (* get_range_by_name_fc) (const GExeFormat *, const char *, mrange_t *);
-
+typedef bool (* translate_virt_fc) (GExecutableFormat *, virt_t, vmpa2t *);
/* Format d'exécutable générique (instance) */
-struct _GExeFormat
+struct _GExecutableFormat
{
- GBinFormat parent; /* A laisser en premier */
+ GProgramFormat parent; /* A laisser en premier */
- GDbgFormat **debugs; /* Informations de débogage */
- size_t debugs_count; /* Nombre de ces informations */
-
- GBinPortion **user_portions; /* Couches de morceaux binaires*/
- size_t user_count; /* Nombre de ces portions */
- GBinPortion *portions; /* Couches de morceaux binaires*/
- GMutex mutex; /* Accès à l'arborescence */
+ GBinaryPortion *portions; /* Couches de morceaux binaires*/
};
/* Format d'exécutable générique (classe) */
-struct _GExeFormatClass
+struct _GExecutableFormatClass
{
- GBinFormatClass parent; /* A laisser en premier */
+ GProgramFormatClass parent; /* A laisser en premier */
get_target_machine_fc get_machine; /* Architecture ciblée */
+
get_main_addr_fc get_main_addr; /* Obtention d'adresse première*/
refine_portions_fc refine_portions; /* Décrit les portions binaires*/
translate_phys_fc translate_phys; /* Correspondance phys -> vmpa */
translate_virt_fc translate_virt; /* Correspondance virt -> vmpa */
- get_range_by_name_fc get_range_by_name; /* Emplacement de sections */
-
};
-/* Crée les portions potentiellement utiles aux traductions. */
-void g_executable_format_setup_portions(GExeFormat *, GtkStatusStack *);
+/* Met en place un nouveau contenu binaire à analyser. */
+bool g_executable_format_create(GExecutableFormat *, GBinContent *);
-/* Effectue les ultimes opérations de chargement d'un binaire. */
-bool g_executable_format_complete_loading(GExeFormat *, wgroup_id_t, GtkStatusStack *);
+/* Fournit l'emplacement correspondant à une position physique. */
+bool g_executable_format_translate_offset_into_vmpa_without_virt(const GExecutableFormat *, phys_t, vmpa2t *);
/* Fournit l'emplacement correspondant à une position physique. */
-bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *, phys_t, vmpa2t *);
+bool g_executable_format_translate_offset_into_vmpa_with_portions(GExecutableFormat *, phys_t, vmpa2t *);
/* Fournit l'emplacement correspondant à une adresse virtuelle. */
-bool g_exe_format_without_virt_translate_address_into_vmpa(const GExeFormat *, virt_t, vmpa2t *);
-
-/* Fournit l'emplacement correspondant à une position physique. */
-bool g_exe_format_translate_offset_into_vmpa_using_portions(GExeFormat *, phys_t, vmpa2t *);
+bool g_executable_format_translate_address_into_vmpa_without_virt(const GExecutableFormat *, virt_t, vmpa2t *);
/* Fournit l'emplacement correspondant à une adresse virtuelle. */
-bool g_exe_format_translate_address_into_vmpa_using_portions(GExeFormat *, virt_t, vmpa2t *);
+bool g_executable_format_translate_address_into_vmpa_with_portions(GExecutableFormat *, virt_t, vmpa2t *);
diff --git a/src/format/executable.c b/src/format/executable.c
index 26c418e..d0fc3e2 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -27,35 +27,48 @@
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
-#include <stdlib.h>
#include <i18n.h>
#include "executable-int.h"
-#include "format.h"
#include "../core/logs.h"
-#include "../plugins/pglist.h"
+/* ------------------------- GESTION D'UN FORMAT EXECUTABLE ------------------------- */
+
+
/* Initialise la classe des formats d'exécutables génériques. */
-static void g_executable_format_class_init(GExeFormatClass *);
+static void g_executable_format_class_init(GExecutableFormatClass *);
/* Initialise une instance de format d'exécutable générique. */
-static void g_executable_format_init(GExeFormat *);
+static void g_executable_format_init(GExecutableFormat *);
/* Supprime toutes les références externes. */
-static void g_executable_format_dispose(GExeFormat *);
+static void g_executable_format_dispose(GExecutableFormat *);
/* Procède à la libération totale de la mémoire. */
-static void g_executable_format_finalize(GExeFormat *);
+static void g_executable_format_finalize(GExecutableFormat *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Assure l'interprétation d'un format en différé. */
+static bool g_executable_format_analyze(GExecutableFormat *);
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION D'UN FORMAT EXECUTABLE */
+/* ---------------------------------------------------------------------------------- */
+
/* Indique le type défini pour un format d'exécutable générique. */
-G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT);
+G_DEFINE_TYPE(GExecutableFormat, g_executable_format, G_TYPE_PROGRAM_FORMAT);
/******************************************************************************
@@ -70,15 +83,20 @@ G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT);
* *
******************************************************************************/
-static void g_executable_format_class_init(GExeFormatClass *klass)
+static void g_executable_format_class_init(GExecutableFormatClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
+ GKnownFormatClass *known; /* Version de format connu */
object = G_OBJECT_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_executable_format_dispose;
object->finalize = (GObjectFinalizeFunc)g_executable_format_finalize;
+ known = G_KNOWN_FORMAT_CLASS(klass);
+
+ known->analyze = (known_analyze_fc)g_executable_format_analyze;
+
}
@@ -94,9 +112,9 @@ static void g_executable_format_class_init(GExeFormatClass *klass)
* *
******************************************************************************/
-static void g_executable_format_init(GExeFormat *format)
+static void g_executable_format_init(GExecutableFormat *format)
{
- g_mutex_init(&format->mutex);
+ format->portions = NULL;
}
@@ -113,20 +131,10 @@ static void g_executable_format_init(GExeFormat *format)
* *
******************************************************************************/
-static void g_executable_format_dispose(GExeFormat *format)
+static void g_executable_format_dispose(GExecutableFormat *format)
{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < format->debugs_count; i++)
- g_clear_object(&format->debugs[i]);
-
- for (i = 0; i < format->user_count; i++)
- g_clear_object(&format->user_portions[i]);
-
g_clear_object(&format->portions);
- g_mutex_clear(&format->mutex);
-
G_OBJECT_CLASS(g_executable_format_parent_class)->dispose(G_OBJECT(format));
}
@@ -144,14 +152,8 @@ static void g_executable_format_dispose(GExeFormat *format)
* *
******************************************************************************/
-static void g_executable_format_finalize(GExeFormat *format)
+static void g_executable_format_finalize(GExecutableFormat *format)
{
- if (format->debugs != NULL)
- free(format->debugs);
-
- if (format->user_portions != NULL)
- free(format->user_portions);
-
G_OBJECT_CLASS(g_executable_format_parent_class)->finalize(G_OBJECT(format));
}
@@ -159,79 +161,66 @@ static void g_executable_format_finalize(GExeFormat *format)
/******************************************************************************
* *
-* Paramètres : format = informations chargées à compléter. *
-* info = informations de débogage à lier. *
+* Paramètres : format = description du format à initialiser pleinement. *
+* content = contenu binaire à parcourir. *
* *
-* Description : Rajoute des informations de débogage à un exécutable. *
+* Description : Met en place un nouveau contenu binaire à analyser. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_exe_format_add_debug_info(GExeFormat *format, GDbgFormat *info)
+bool g_executable_format_create(GExecutableFormat *format, GBinContent *content)
{
- const char *desc; /* Description humaine associée*/
+ bool result; /* Bilan à retourner */
+ vmpa2t addr; /* Emplacement vide de sens */
+ phys_t length; /* Taille de portion globale */
- desc = g_known_format_get_description(G_KNOWN_FORMAT(info));
+ result = g_program_format_create(G_PROGRAM_FORMAT(format), content);
+ if (!result) goto exit;
- if (desc == NULL)
- log_simple_message(LMT_WARNING, _("Unnamed debug information"));
- else
- log_variadic_message(LMT_INFO, _("Found debug information: %s"), desc);
+ /* Définition de portions */
- format->debugs = realloc(format->debugs, ++format->debugs_count * sizeof(GDbgFormat *));
-
- format->debugs[format->debugs_count - 1] = info;
+ /**
+ * Avant de lire l'entête du format, on ne sait pas où on se trouve !
+ */
+ init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
-}
+ length = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content);
+ format->portions = g_binary_portion_new(&addr, length);
-/******************************************************************************
-* *
-* Paramètres : format = informations chargées à consulter. *
-* *
-* Description : Compte le nombre de formats de débogage liés à l'exécutable. *
-* *
-* Retour : Nombre de formats de débogage attachés. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ exit:
-size_t g_exe_format_count_debug_info(const GExeFormat *format)
-{
- return format->debugs_count;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : format = informations chargées à consulter. *
-* index = indice des informations à transmettre. *
+* Paramètres : format = description du format exécutable à consulter. *
* *
-* Description : Fournit un format de débogage attaché à l'exécutable. *
+* Description : Indique le type d'architecture visée par le format. *
* *
-* Retour : Informations de débogage attachées. *
+* Retour : Identifiant de l'architecture ciblée par le format. *
* *
* Remarques : - *
* *
******************************************************************************/
-GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index)
+char *g_executable_format_get_target_machine(const GExecutableFormat *format)
{
- GDbgFormat *result; /* Format à retourner */
+ char *result; /* Désignation à retourner */
+ GExecutableFormatClass *class; /* Classe de l'instance */
- if (index >= format->debugs_count)
- result = NULL;
+ class = G_EXECUTABLE_FORMAT_GET_CLASS(format);
- else
- {
- result = format->debugs[index];
- g_object_ref(G_OBJECT(result));
- }
+ result = class->get_machine(format);
+
+ //assert(result != NULL);
return result;
@@ -240,56 +229,96 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index)
/******************************************************************************
* *
-* Paramètres : format = informations chargées à consulter. *
+* Paramètres : format = description de l'exécutable à consulter. *
+* addr = adresse principale trouvée si possible. [OUT] *
* *
-* Description : Indique le type d'architecture visée par le format. *
+* Description : Fournit l'adresse principale associée à un format. *
* *
-* Retour : Identifiant de l'architecture ciblée par le format. *
+* Retour : Validité de l'adresse transmise. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_exe_format_get_target_machine(const GExeFormat *format)
+bool g_executable_format_get_main_address(GExecutableFormat *format, vmpa2t *addr)
{
- return G_EXE_FORMAT_GET_CLASS(format)->get_machine(format);
+ bool result; /* Bilan à retourner */
+ GExecutableFormatClass *class; /* Classe de l'instance */
+
+ class = G_EXECUTABLE_FORMAT_GET_CLASS(format);
+
+ result = class->get_main_addr(format, addr);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* addr = adresse principale trouvée si possible. [OUT] *
+* Paramètres : format = description de l'exécutable à modifier. *
+* portion = portion à inclure dans les définitions du format. *
+* origin = source de définition de la portion fournie. *
* *
-* Description : Fournit l'adresse principale associée à un format. *
+* Description : Procède à l'enregistrement d'une portion dans un format. *
* *
-* Retour : Bilan des recherches. *
+* Retour : Bilan de l'opération : true si inclusion, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_exe_format_get_main_address(GExeFormat *format, vmpa2t *addr)
+bool g_executable_format_include_portion(GExecutableFormat *format, GBinaryPortion *portion, const vmpa2t *origin)
{
bool result; /* Bilan à retourner */
- GBinFormat *base; /* Version d'instance parente */
+ phys_t available; /* Taille totale du bianire */
+ const mrange_t *range; /* Emplacement de la portion */
+ phys_t start; /* Début de zone de la portion */
+ vmpa2t no_origin; /* Emplacement inconnu */
+ char *msg; /* Description d'une erreur */
+ phys_t remaining; /* Taille maximale envisageable*/
+ bool truncated; /* Modification faite ? */
result = false;
- if (G_EXE_FORMAT_GET_CLASS(format)->get_main_addr != NULL)
- result = G_EXE_FORMAT_GET_CLASS(format)->get_main_addr(format, addr);
+ available = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content);
+
+ range = g_binary_portion_get_range(portion);
+
+ start = get_phy_addr(get_mrange_addr(range));
+
+ if (get_mrange_length(range) == 0)
+ log_variadic_message(LMT_BAD_BINARY, _("The binary portion '%s' is empty and thus useless... Discarding!"),
+ g_binary_portion_get_desc(portion));
- if (!result)
+ else if (start >= available)
{
- base = G_BIN_FORMAT(format);
+ if (origin == NULL)
+ {
+ init_vmpa(&no_origin, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+ origin = &no_origin;
+ }
- g_rw_lock_reader_lock(&base->pt_lock);
+ asprintf(&msg, _("Defined binary portion '%s' is out of the file scope... Discarding!"),
+ g_binary_portion_get_desc(portion));
- if (base->pt_count[DPL_ENTRY_POINT] > 0)
- result = g_exe_format_translate_address_into_vmpa(format, base->start_points[DPL_ENTRY_POINT][0], addr);
+ //g_binary_format_add_error(G_BIN_FORMAT(format), BFE_STRUCTURE, origin, msg);
- g_rw_lock_reader_unlock(&base->pt_lock);
+ free(msg);
+
+ }
+
+ else
+ {
+ remaining = available - start;
+
+ truncated = g_binary_portion_limit_range(portion, remaining);
+
+ if (truncated)
+ log_variadic_message(LMT_BAD_BINARY, _("Truncated binary portion '%s' to fit the binary content size!"),
+ g_binary_portion_get_desc(portion));
+
+ result = g_binary_portion_include(format->portions, portion);
}
@@ -300,54 +329,39 @@ bool g_exe_format_get_main_address(GExeFormat *format, vmpa2t *addr)
/******************************************************************************
* *
-* Paramètres : format = instance à traiter. *
-* status = barre de statut à tenir informée. *
+* Paramètres : format = description de l'exécutable à consulter. *
* *
-* Description : Crée les portions potentiellement utiles aux traductions. *
+* Description : Fournit la première couche des portions composent le binaire.*
* *
-* Retour : - *
+* Retour : Arborescence des différentes portions binaires. *
* *
-* Remarques : - *
+* Remarques : Le compteur de références de l'instance renvoyée doit être *
+* décrémenté après usage. *
* *
******************************************************************************/
-void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *status)
+GBinaryPortion *g_executable_format_get_portions(GExecutableFormat *format)
{
- vmpa2t addr; /* Emplacement vide de sens */
- phys_t length; /* Taille de portion globale */
- GExeFormatClass *class; /* Classe de l'instance */
- size_t i; /* Boucle de parcours */
-
- /**
- * Avant de lire l'entête du format, on ne sait pas où on se trouve !
- */
- init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+ GBinaryPortion *result; /* Instance à retourner */
- length = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content);
-
- format->portions = g_binary_portion_new(BPC_RAW, &addr, length);
+ result = format->portions;
- class = G_EXE_FORMAT_GET_CLASS(format);
+ assert(result != NULL);
- if (class->refine_portions != NULL)
- class->refine_portions(format);
+ ref_object(result);
- for (i = 0; i < format->user_count; i++)
- {
- g_object_ref(G_OBJECT(format->user_portions[i]));
- g_exe_format_include_portion(format, format->user_portions[i], NULL);
- }
+ return result;
}
/******************************************************************************
* *
-* Paramètres : format = instance à traiter. *
-* gid = groupe de travail dédié. *
-* status = barre de statut à tenir informée. *
+* Paramètres : format = description de l'exécutable à consulter. *
+* off = position physique à retrouver. *
+* pos = position correspondante. [OUT] *
* *
-* Description : Effectue les ultimes opérations de chargement d'un binaire. *
+* Description : Fournit l'emplacement correspondant à une position physique. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -355,28 +369,14 @@ void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *stat
* *
******************************************************************************/
-bool g_executable_format_complete_loading(GExeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+bool g_executable_format_translate_offset_into_vmpa(GExecutableFormat *format, phys_t off, vmpa2t *pos)
{
- bool result; /* Bilan à faire remonter */
- size_t count; /* Qté d'infos supplémentaires */
- size_t i; /* Boucle de parcours */
- GDbgFormat *dbg; /* Informations de débogage */
-
- result = true;
-
- attach_debug_format(format);
-
- count = g_exe_format_count_debug_info(format);
-
- for (i = 0; i < count && result; i++)
- {
- dbg = g_exe_format_get_debug_info(format, i);
-
- result = g_known_format_analyze(G_KNOWN_FORMAT(dbg), gid, status);
+ bool result; /* Bilan à retourner */
+ GExecutableFormatClass *class; /* Classe de l'instance */
- g_object_unref(G_OBJECT(dbg));
+ class = G_EXECUTABLE_FORMAT_GET_CLASS(format);
- }
+ result = class->translate_phys(format, off, pos);
return result;
@@ -385,105 +385,52 @@ bool g_executable_format_complete_loading(GExeFormat *format, wgroup_id_t gid, G
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à modifier. *
-* portion = portion à inclure dans les définitions du format. *
+* Paramètres : format = description de l'exécutable à consulter. *
+* off = position physique à retrouver. *
+* pos = position correspondante. [OUT] *
* *
-* Description : Enregistre une portion artificielle pour le format. *
+* Description : Fournit l'emplacement correspondant à une position physique. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_exe_format_register_user_portion(GExeFormat *format, GBinPortion *portion)
+bool g_executable_format_translate_offset_into_vmpa_without_virt(const GExecutableFormat *format, phys_t off, vmpa2t *pos)
{
- g_mutex_lock(&format->mutex);
+ init_vmpa(pos, off, VMPA_NO_VIRTUAL);
- format->user_portions = realloc(format->user_portions, ++format->user_count * sizeof(GBinPortion *));
-
- format->user_portions[format->user_count - 1] = portion;
-
- g_mutex_unlock(&format->mutex);
+ return true;
}
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à modifier. *
-* portion = portion à inclure dans les définitions du format. *
-* origin = source de définition de la portion fournie. *
+* Paramètres : format = description de l'exécutable à consulter. *
+* off = position physique à retrouver. *
+* pos = position correspondante. [OUT] *
* *
-* Description : Procède à l'enregistrement d'une portion dans un format. *
+* Description : Fournit l'emplacement correspondant à une position physique. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, const vmpa2t *origin)
+bool g_executable_format_translate_offset_into_vmpa_with_portions(GExecutableFormat *format, phys_t off, vmpa2t *pos)
{
- phys_t available; /* Taille totale du bianire */
- const mrange_t *range; /* Emplacement de la portion */
- phys_t start; /* Début de zone de la portion */
- vmpa2t no_origin; /* Emplacement inconnu */
- char *msg; /* Description d'une erreur */
- phys_t remaining; /* Taille maximale envisageable*/
- bool truncated; /* Modification faite ? */
-
- available = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content);
-
- range = g_binary_portion_get_range(portion);
-
- start = get_phy_addr(get_mrange_addr(range));
-
- if (get_mrange_length(range) == 0)
- {
- log_variadic_message(LMT_BAD_BINARY, _("The binary portion '%s' is empty and thus useless... Discarding!"),
- g_binary_portion_get_desc(portion));
-
- g_object_unref(G_OBJECT(portion));
-
- }
-
- else if (start >= available)
- {
- if (origin == NULL)
- {
- init_vmpa(&no_origin, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
- origin = &no_origin;
- }
-
- asprintf(&msg, _("Defined binary portion '%s' is out of the file scope... Discarding!"),
- g_binary_portion_get_desc(portion));
-
- g_binary_format_add_error(G_BIN_FORMAT(format), BFE_STRUCTURE, origin, msg);
-
- free(msg);
-
- g_object_unref(G_OBJECT(portion));
+ bool result; /* Bilan à retourner */
- }
+ if (format->portions == NULL)
+ result = false;
else
- {
- remaining = available - start;
-
- truncated = g_binary_portion_limit_range(portion, remaining);
-
- if (truncated)
- log_variadic_message(LMT_BAD_BINARY, _("Truncated binary portion '%s' to fit the binary content size!"),
- g_binary_portion_get_desc(portion));
+ result = g_binary_portion_translate_offset_into_vmpa(format->portions, off, pos);
- g_mutex_lock(&format->mutex);
-
- g_binary_portion_include(format->portions, portion);
-
- g_mutex_unlock(&format->mutex);
-
- }
+ return result;
}
@@ -491,28 +438,25 @@ void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, cons
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
+* addr = adresse virtuelle à retrouver. *
+* pos = position correspondante. [OUT] *
* *
-* Description : Fournit la première couche des portions composent le binaire.*
+* Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
* *
-* Retour : Arborescence des différentes portions binaires. *
+* Retour : Bilan de l'opération. *
* *
-* Remarques : Le compteur de références de l'instance renvoyée doit être *
-* décrémenté après usage. *
+* Remarques : - *
* *
******************************************************************************/
-GBinPortion *g_exe_format_get_portions(GExeFormat *format)
+bool g_executable_format_translate_address_into_vmpa(GExecutableFormat *format, virt_t addr, vmpa2t *pos)
{
- GBinPortion *result; /* Instance à retourner */
-
- g_mutex_lock(&format->mutex);
-
- result = format->portions;
+ bool result; /* Bilan à retourner */
+ GExecutableFormatClass *class; /* Classe de l'instance */
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
+ class = G_EXECUTABLE_FORMAT_GET_CLASS(format);
- g_mutex_unlock(&format->mutex);
+ result = class->translate_virt(format, addr, pos);
return result;
@@ -522,10 +466,10 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format)
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
-* off = position physique à retrouver. *
+* addr = adresse virtuelle à retrouver. *
* pos = position correspondante. [OUT] *
* *
-* Description : Fournit l'emplacement correspondant à une position physique. *
+* Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -533,13 +477,21 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format)
* *
******************************************************************************/
-bool g_exe_format_translate_offset_into_vmpa(GExeFormat *format, phys_t off, vmpa2t *pos)
+bool g_executable_format_translate_address_into_vmpa_without_virt(const GExecutableFormat *format, virt_t addr, vmpa2t *pos)
{
- bool result; /* Bilan à retourner */
+ /**
+ * S'il n'y a pas de notion de mémoire virtuelle, positions physiques et
+ * adresses virtuelles se confondent.
+ *
+ * On reste néanmoins cohérent, et on n'utilise donc pas d'adresse virtuelle.
+ *
+ * Les sauts dans le code renvoient de façon transparente vers des positions
+ * physiques.
+ */
- result = G_EXE_FORMAT_GET_CLASS(format)->translate_phys(format, off, pos);
+ init_vmpa(pos, addr, VMPA_NO_VIRTUAL);
- return result;
+ return true;
}
@@ -558,24 +510,32 @@ bool g_exe_format_translate_offset_into_vmpa(GExeFormat *format, phys_t off, vmp
* *
******************************************************************************/
-bool g_exe_format_translate_address_into_vmpa(GExeFormat *format, virt_t addr, vmpa2t *pos)
+bool g_executable_format_translate_address_into_vmpa_with_portions(GExecutableFormat *format, virt_t addr, vmpa2t *pos)
{
bool result; /* Bilan à retourner */
- result = G_EXE_FORMAT_GET_CLASS(format)->translate_virt(format, addr, pos);
+ if (format->portions == NULL)
+ result = false;
+
+ else
+ result = g_binary_portion_translate_address_into_vmpa(format->portions, addr, pos);
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* name = nom de la section recherchée. *
-* range = emplacement en mémoire à renseigner. [OUT] *
+* Paramètres : format = format chargé dont l'analyse est lancée. *
* *
-* Description : Fournit l'emplacement d'une section donnée. *
+* Description : Assure l'interprétation d'un format en différé. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -583,18 +543,17 @@ bool g_exe_format_translate_address_into_vmpa(GExeFormat *format, virt_t addr, v
* *
******************************************************************************/
-bool g_exe_format_get_section_range_by_name(const GExeFormat *format, const char *name, mrange_t *range)
+static bool g_executable_format_analyze(GExecutableFormat *format)
{
bool result; /* Bilan à retourner */
- GExeFormatClass *class; /* Classe de l'instance */
+ GExecutableFormatClass *class; /* Classe de l'instance */
- class = G_EXE_FORMAT_GET_CLASS(format);
-
- if (class->get_range_by_name == NULL)
- result = false;
+ class = G_EXECUTABLE_FORMAT_GET_CLASS(format);
+ if (class->refine_portions != NULL)
+ result = class->refine_portions(format);
else
- result = class->get_range_by_name(format, name, range);
+ result = true;
return result;
diff --git a/src/format/executable.h b/src/format/executable.h
index 4f5abc7..da71d66 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* executable.h - prototypes pour le support des formats d'exécutables
*
- * Copyright (C) 2009-2019 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,88 +25,56 @@
#define _FORMAT_EXECUTABLE_H
-#include <glib-object.h>
+#include <stdbool.h>
-#include "debuggable.h"
-#include "../glibext/gbinportion.h"
+#include "../glibext/helpers.h"
+#include "../glibext/portion.h"
-#define G_TYPE_EXE_FORMAT g_executable_format_get_type()
-#define G_EXE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_EXE_FORMAT, GExeFormat))
-#define G_IS_EXE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_EXE_FORMAT))
-#define G_EXE_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_EXE_FORMAT, GExeFormatClass))
-#define G_IS_EXE_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_EXE_FORMAT))
-#define G_EXE_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_EXE_FORMAT, GExeFormatClass))
+#define G_TYPE_EXECUTABLE_FORMAT (g_executable_format_get_type())
+DECLARE_GTYPE(GExecutableFormat, g_executable_format, G, EXECUTABLE_FORMAT);
-/* Format d'exécutable générique (instance) */
-typedef struct _GExeFormat GExeFormat;
-
-/* Format d'exécutable générique (classe) */
-typedef struct _GExeFormatClass GExeFormatClass;
-
-
-/* Indique le type défini pour un format d'exécutable générique. */
-GType g_executable_format_get_type(void);
-
-/* Rajoute des informations de débogage à un exécutable. */
-void g_exe_format_add_debug_info(GExeFormat *, GDbgFormat *);
-
-/* Compte le nombre de formats de débogage liés à l'exécutable. */
-size_t g_exe_format_count_debug_info(const GExeFormat *);
-
-/* Fournit un format de débogage attaché à l'exécutable. */
-GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *, size_t);
/* Indique le type d'architecture visée par le format. */
-const char *g_exe_format_get_target_machine(const GExeFormat *);
+char *g_executable_format_get_target_machine(const GExecutableFormat *);
/* Fournit l'adresse principale associée à un format. */
-bool g_exe_format_get_main_address(GExeFormat *, vmpa2t *);
-
-/* Enregistre une portion artificielle pour le format. */
-void g_exe_format_register_user_portion(GExeFormat *, GBinPortion *);
+bool g_executable_format_get_main_address(GExecutableFormat *, vmpa2t *);
/* Procède à l'enregistrement d'une portion dans un format. */
-void g_exe_format_include_portion(GExeFormat *, GBinPortion *, const vmpa2t *);
+bool g_executable_format_include_portion(GExecutableFormat *, GBinaryPortion *, const vmpa2t *);
/* Fournit la première couche des portions composent le binaire. */
-GBinPortion *g_exe_format_get_portions(GExeFormat *);
-
-/* Fournit les espaces mémoires des portions exécutables. */
-mrange_t *g_exe_format_get_x_ranges(GExeFormat *, size_t *);
+GBinaryPortion *g_executable_format_get_portions(GExecutableFormat *);
/* Fournit l'emplacement correspondant à une position physique. */
-bool g_exe_format_translate_offset_into_vmpa(GExeFormat *, phys_t, vmpa2t *);
+bool g_executable_format_translate_offset_into_vmpa(GExecutableFormat *, phys_t, vmpa2t *);
/* Fournit l'emplacement correspondant à une position physique. */
-bool g_exe_format_translate_address_into_vmpa(GExeFormat *, virt_t, vmpa2t *);
+bool g_executable_format_translate_address_into_vmpa(GExecutableFormat *, virt_t, vmpa2t *);
-#define g_exe_format_translate_offset_into_address(fmt, off, addr) \
- ({ \
- bool __result; \
- vmpa2t __pos; \
- __result = g_exe_format_translate_offset_into_vmpa(fmt, off, &__pos); \
- *addr = get_virt_addr(&__pos); \
- __result; \
+#define g_executable_format_translate_offset_into_address(fmt, off, addr) \
+ ({ \
+ bool __result; \
+ vmpa2t __pos; \
+ __result = g_executable_format_translate_offset_into_vmpa(fmt, off, &__pos); \
+ *addr = get_virt_addr(&__pos); \
+ __result; \
})
-#define g_exe_format_translate_address_into_offset(fmt, addr, off) \
- ({ \
- bool __result; \
- vmpa2t __pos; \
- __result = g_exe_format_translate_address_into_vmpa(fmt, addr, &__pos); \
- *off = get_phy_addr(&__pos); \
- __result; \
+#define g_executable_format_translate_address_into_offset(fmt, addr, off) \
+ ({ \
+ bool __result; \
+ vmpa2t __pos; \
+ __result = g_executable_format_translate_address_into_vmpa(fmt, addr, &__pos); \
+ *off = get_phy_addr(&__pos); \
+ __result; \
})
-/* Fournit l'emplacement d'une section donnée. */
-bool g_exe_format_get_section_range_by_name(const GExeFormat *, const char *, mrange_t *);
-
-
#endif /* _FORMAT_EXECUTABLE_H */
diff --git a/src/format/flat-int.h b/src/format/flat-int.h
index d785e5f..f858ba3 100644
--- a/src/format/flat-int.h
+++ b/src/format/flat-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* flat-int.h - prototypes de code utile aux formats d'exécutables à plat
*
- * Copyright (C) 2018 Cyrille Bagard
+ * Copyright (C) 2018-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -35,7 +35,7 @@
/* Format d'exécutable à plat (instance) */
struct _GFlatFormat
{
- GExeFormat parent; /* A laisser en premier */
+ GExecutableFormat parent; /* A laisser en premier */
char *machine; /* Architecture imposée */
SourceEndian endian; /* Boutisme imposé */
@@ -45,10 +45,14 @@ struct _GFlatFormat
/* Format d'exécutable à plat (classe) */
struct _GFlatFormatClass
{
- GExeFormatClass parent; /* A laisser en premier */
+ GExecutableFormatClass parent; /* A laisser en premier */
};
+/* Met en place une nouvelle instance de format à plat. */
+bool g_flat_format_create(GFlatFormat *, GBinContent *, const char *, SourceEndian);
+
+
#endif /* _FORMAT_FLAT_INT_H */
diff --git a/src/format/flat.c b/src/format/flat.c
index 6b8b074..51f37fa 100644
--- a/src/format/flat.c
+++ b/src/format/flat.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* flat.c - support des formats à plat
*
- * Copyright (C) 2018-2019 Cyrille Bagard
+ * Copyright (C) 2018-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -32,6 +32,9 @@
+/* ------------------------- DEFINITION D'UN NOUVEAU FORMAT ------------------------- */
+
+
/* Initialise la classe des formats d'exécutables à plat. */
static void g_flat_format_class_init(GFlatFormatClass *);
@@ -44,28 +47,39 @@ static void g_flat_format_dispose(GFlatFormat *);
/* Procède à la libération totale de la mémoire. */
static void g_flat_format_finalize(GFlatFormat *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Indique la désignation interne du format. */
static char *g_flat_format_get_key(const GFlatFormat *);
/* Fournit une description humaine du format. */
static char *g_flat_format_get_description(const GFlatFormat *);
-/* Assure l'interprétation d'un format en différé. */
-static bool g_flat_format_analyze(GFlatFormat *, wgroup_id_t, GtkStatusStack *);
-
/* Informe quant au boutisme utilisé. */
static SourceEndian g_flat_format_get_endianness(const GFlatFormat *);
/* Indique le type d'architecture visée par le format. */
-static const char *g_flat_format_get_target_machine(const GFlatFormat *);
+static char *g_flat_format_get_target_machine(const GFlatFormat *);
+
+#if 0
/* Fournit l'adresse principale associée à un format à plat. */
static bool g_flat_format_get_main_address(GFlatFormat *, vmpa2t *);
+#endif
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU FORMAT */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un format d'exécutable à plat. */
-G_DEFINE_TYPE(GFlatFormat, g_flat_format, G_TYPE_EXE_FORMAT);
+G_DEFINE_TYPE(GFlatFormat, g_flat_format, G_TYPE_EXECUTABLE_FORMAT);
/******************************************************************************
@@ -84,8 +98,8 @@ static void g_flat_format_class_init(GFlatFormatClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GKnownFormatClass *known; /* Version de format connu */
- GBinFormatClass *fmt; /* Version en format basique */
- GExeFormatClass *exe; /* Version en exécutable */
+ GProgramFormatClass *prgm; /* Version en format basique */
+ GExecutableFormatClass *exe; /* Version en exécutable */
object = G_OBJECT_CLASS(klass);
@@ -97,19 +111,18 @@ static void g_flat_format_class_init(GFlatFormatClass *klass)
known->get_key = (known_get_key_fc)g_flat_format_get_key;
known->get_desc = (known_get_desc_fc)g_flat_format_get_description;
- known->analyze = (known_analyze_fc)g_flat_format_analyze;
-
- fmt = G_BIN_FORMAT_CLASS(klass);
+ prgm = G_PROGRAM_FORMAT_CLASS(klass);
- fmt->get_endian = (format_get_endian_fc)g_flat_format_get_endianness;
+ prgm->get_endian = (program_get_endian_fc)g_flat_format_get_endianness;
- exe = G_EXE_FORMAT_CLASS(klass);
+ exe = G_EXECUTABLE_FORMAT_CLASS(klass);
exe->get_machine = (get_target_machine_fc)g_flat_format_get_target_machine;
+#if 0
exe->get_main_addr = (get_main_addr_fc)g_flat_format_get_main_address;
-
- exe->translate_phys = (translate_phys_fc)g_exe_format_translate_offset_into_vmpa_using_portions;
- exe->translate_virt = (translate_virt_fc)g_exe_format_translate_address_into_vmpa_using_portions;
+#endif
+ exe->translate_phys = g_executable_format_translate_offset_into_vmpa_with_portions;
+ exe->translate_virt = g_executable_format_translate_address_into_vmpa_with_portions;
}
@@ -178,8 +191,10 @@ static void g_flat_format_finalize(GFlatFormat *format)
/******************************************************************************
* *
* Paramètres : content = contenu binaire à parcourir. *
+* machine = architecture déterminée pour le code. *
+ endian = boutisme à observer pour les données. *
* *
-* Description : Prend en charge un nouveau format à plat. *
+* Description : Crée une nouvelle instance de format à plat. *
* *
* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.*
* *
@@ -187,62 +202,72 @@ static void g_flat_format_finalize(GFlatFormat *format)
* *
******************************************************************************/
-GExeFormat *g_flat_format_new(GBinContent *content, const char *machine, SourceEndian endian)
+GFlatFormat *g_flat_format_new(GBinContent *content, const char *machine, SourceEndian endian)
{
GFlatFormat *result; /* Structure à retourner */
result = g_object_new(G_TYPE_FLAT_FORMAT, NULL);
- g_known_format_set_content(G_KNOWN_FORMAT(result), content);
+ if (!g_flat_format_create(result, content, machine, endian))
+ g_clear_object(&result);
- result->machine = strdup(machine);
- result->endian = endian;
-
- return G_EXE_FORMAT(result);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à consulter. *
+* Paramètres : format = description du format connu à consulter. *
+* content = contenu binaire à parcourir. *
+* machine = architecture déterminée pour le code. *
+ endian = boutisme à observer pour les données. *
* *
-* Description : Indique la désignation interne du format. *
+* Description : Met en place une nouvelle instance de format à plat. *
* *
-* Retour : Désignation du format. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static char *g_flat_format_get_key(const GFlatFormat *format)
+bool g_flat_format_create(GFlatFormat *format, GBinContent *content, const char *machine, SourceEndian endian)
{
- char *result; /* Désignation à retourner */
+ bool result; /* Bilan à retourner */
- result = strdup("flat");
+ result = g_executable_format_create(G_EXECUTABLE_FORMAT(format), content);
+
+ format->machine = strdup(machine);
+ format->endian = endian;
return result;
}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
* *
-* Description : Fournit une description humaine du format. *
+* Description : Indique la désignation interne du format. *
* *
-* Retour : Description du format. *
+* Retour : Désignation du format. *
* *
* Remarques : - *
* *
******************************************************************************/
-static char *g_flat_format_get_description(const GFlatFormat *format)
+static char *g_flat_format_get_key(const GFlatFormat *format)
{
char *result; /* Désignation à retourner */
- result = strdup("Flat executable format");
+ result = strdup("flat");
return result;
@@ -251,25 +276,21 @@ static char *g_flat_format_get_description(const GFlatFormat *format)
/******************************************************************************
* *
-* Paramètres : format = format chargé dont l'analyse est lancée. *
-* gid = groupe de travail dédié. *
-* status = barre de statut à tenir informée. *
+* Paramètres : format = description de l'exécutable à consulter. *
* *
-* Description : Assure l'interprétation d'un format en différé. *
+* Description : Fournit une description humaine du format. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Description du format. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_flat_format_analyze(GFlatFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static char *g_flat_format_get_description(const GFlatFormat *format)
{
- bool result; /* Bilan à retourner */
-
- result = true;
+ char *result; /* Désignation à retourner */
- g_executable_format_setup_portions(G_EXE_FORMAT(format), status);
+ result = strdup("Flat executable format");
return result;
@@ -290,14 +311,18 @@ static bool g_flat_format_analyze(GFlatFormat *format, wgroup_id_t gid, GtkStatu
static SourceEndian g_flat_format_get_endianness(const GFlatFormat *format)
{
- return format->endian;
+ SourceEndian result; /* Valeur à retourner */
+
+ result = format->endian;
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : format = informations chargées à consulter. *
+* Paramètres : format = description du format exécutable à consulter. *
* *
* Description : Indique le type d'architecture visée par le format. *
* *
@@ -307,17 +332,17 @@ static SourceEndian g_flat_format_get_endianness(const GFlatFormat *format)
* *
******************************************************************************/
-static const char *g_flat_format_get_target_machine(const GFlatFormat *format)
+static char *g_flat_format_get_target_machine(const GFlatFormat *format)
{
- const char *result; /* Identifiant à retourner */
+ char *result; /* Identifiant à retourner */
- result = format->machine;
+ result = strdup(format->machine);
return result;
}
-
+#if 0
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à consulter. *
@@ -350,3 +375,5 @@ static bool g_flat_format_get_main_address(GFlatFormat *format, vmpa2t *addr)
return result;
}
+
+#endif
diff --git a/src/format/flat.h b/src/format/flat.h
index 83c5e3c..2168221 100644
--- a/src/format/flat.h
+++ b/src/format/flat.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* flat.h - prototypes pour le support des formats à plat
*
- * Copyright (C) 2018 Cyrille Bagard
+ * Copyright (C) 2018-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,34 +25,19 @@
#define _FORMAT_FLAT_H
-#include <glib-object.h>
-
-
-#include "executable.h"
#include "../analysis/content.h"
+#include "../glibext/helpers.h"
-#define G_TYPE_FLAT_FORMAT g_flat_format_get_type()
-#define G_FLAT_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_FLAT_FORMAT, GFlatFormat))
-#define G_IS_FLAT_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_FLAT_FORMAT))
-#define G_FLAT_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_FLAT_FORMAT, GFlatFormatClass))
-#define G_IS_FLAT_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_FLAT_FORMAT))
-#define G_FLAT_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_FLAT_FORMAT, GFlatFormatClass))
-
-
-/* Format d'exécutable à plat (instance) */
-typedef struct _GFlatFormat GFlatFormat;
+#define G_TYPE_FLAT_FORMAT (g_flat_format_get_type())
-/* Format d'exécutable à plat (classe) */
-typedef struct _GFlatFormatClass GFlatFormatClass;
+DECLARE_GTYPE(GFlatFormat, g_flat_format, G, FLAT_FORMAT);
-/* Indique le type défini pour un format d'exécutable à plat. */
-GType g_flat_format_get_type(void);
-/* Prend en charge un nouveau format à plat. */
-GExeFormat *g_flat_format_new(GBinContent *, const char *, SourceEndian);
+/* Crée une nouvelle instance de format à plat. */
+GFlatFormat *g_flat_format_new(GBinContent *, const char *, SourceEndian);
diff --git a/src/format/known-int.h b/src/format/known-int.h
index 3328a96..75d0dab 100644
--- a/src/format/known-int.h
+++ b/src/format/known-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* known-int.h - prototypes utiles aux formats binaires reconnus
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,7 +26,7 @@
#include "known.h"
-#include "../analysis/storage/storage.h"
+//#include "../analysis/storage/storage.h"
@@ -37,16 +37,15 @@ typedef char * (* known_get_key_fc) (const GKnownFormat *);
typedef char * (* known_get_desc_fc) (const GKnownFormat *);
/*Assure l'interprétation d'un format en différé. */
-typedef bool (* known_analyze_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack *);
-
-/* Réalise un traitement post-désassemblage. */
-typedef void (* known_complete_analysis_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack *);
+typedef bool (* known_analyze_fc) (GKnownFormat *);
+#if 0
/* Charge un format depuis une mémoire tampon. */
typedef bool (* load_known_fc) (GKnownFormat *, GObjectStorage *, packed_buffer_t *);
/* Sauvegarde un format dans une mémoire tampon. */
typedef bool (* store_known_fc) (GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+#endif
/* Format binaire générique (instance) */
@@ -67,13 +66,18 @@ struct _GKnownFormatClass
known_get_desc_fc get_desc; /* Désignation humaine */
known_analyze_fc analyze; /* Interprétation du format */
- known_complete_analysis_fc complete; /* Terminaison d'analyse */
+#if 0
load_known_fc load; /* Chargement depuis un tampon */
store_known_fc store; /* Conservation dans un tampon */
+#endif
};
+/* Met en place un nouveau contenu binaire à analyser. */
+bool g_known_format_create(GKnownFormat *, GBinContent *);
+
+
#endif /* _FORMAT_KNOWN_INT_H */
diff --git a/src/format/known.c b/src/format/known.c
index 7512ae1..bc03793 100644
--- a/src/format/known.c
+++ b/src/format/known.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* format.c - support des différents formats binaires reconnus
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,8 +28,8 @@
#include "known-int.h"
-#include "../analysis/storage/serialize-int.h"
-#include "../plugins/pglist.h"
+//#include "../analysis/storage/serialize-int.h"
+//#include "../plugins/pglist.h"
@@ -43,7 +43,7 @@ static void g_known_format_class_init(GKnownFormatClass *);
static void g_known_format_init(GKnownFormat *);
/* Procède à l'initialisation de l'interface de sérialisation. */
-static void g_known_format_serializable_init(GSerializableObjectInterface *);
+//static void g_known_format_serializable_init(GSerializableObjectInterface *);
/* Supprime toutes les références externes. */
static void g_known_format_dispose(GKnownFormat *);
@@ -56,6 +56,7 @@ static void g_known_format_finalize(GKnownFormat *);
/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+#if 0
/* Charge un format depuis une mémoire tampon. */
static bool _g_known_format_load(GKnownFormat *, GObjectStorage *, packed_buffer_t *);
@@ -67,7 +68,7 @@ static bool _g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffe
/* Sauvegarde un format dans une mémoire tampon. */
static bool g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffer_t *);
-
+#endif
/* ---------------------------------------------------------------------------------- */
@@ -76,8 +77,9 @@ static bool g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffer
/* Indique le type défini pour un format binaire générique. */
-G_DEFINE_TYPE_WITH_CODE(GKnownFormat, g_known_format, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_format_serializable_init));
+//G_DEFINE_TYPE_WITH_CODE(GKnownFormat, g_known_format, G_TYPE_OBJECT,
+// G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_format_serializable_init));
+G_DEFINE_TYPE(GKnownFormat, g_known_format, G_TYPE_OBJECT);
/******************************************************************************
@@ -101,8 +103,10 @@ static void g_known_format_class_init(GKnownFormatClass *klass)
object->dispose = (GObjectFinalizeFunc/* ! */)g_known_format_dispose;
object->finalize = (GObjectFinalizeFunc)g_known_format_finalize;
+ /*
klass->load = (load_known_fc)_g_known_format_load;
klass->store = (store_known_fc)_g_known_format_store;
+ */
}
@@ -126,6 +130,7 @@ static void g_known_format_init(GKnownFormat *format)
}
+#if 0
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
@@ -144,6 +149,7 @@ static void g_known_format_serializable_init(GSerializableObjectInterface *iface
iface->store = (store_serializable_object_cb)g_known_format_store;
}
+#endif
/******************************************************************************
@@ -188,24 +194,27 @@ static void g_known_format_finalize(GKnownFormat *format)
/******************************************************************************
* *
-* Paramètres : format = description du format connu à consulter. *
+* Paramètres : format = description du format à initialiser pleinement. *
* content = contenu binaire à parcourir. *
* *
-* Description : Définit le contenu binaire à analyser. *
+* Description : Met en place un nouveau contenu binaire à analyser. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_known_format_set_content(GKnownFormat *format, GBinContent *content)
+bool g_known_format_create(GKnownFormat *format, GBinContent *content)
{
- assert(format->content == NULL);
+ bool result; /* Bilan à retourner */
- g_object_ref_sink(G_OBJECT(content));
+ result = true;
format->content = content;
+ ref_object(content);
+
+ return result;
}
@@ -251,8 +260,13 @@ GBinContent *g_known_format_get_content(const GKnownFormat *format)
char *g_known_format_get_key(const GKnownFormat *format)
{
char *result; /* Désignation à retourner */
+ GKnownFormatClass *class; /* Classe de l'instance */
+
+ class = G_KNOWN_FORMAT_GET_CLASS(format);
- result = G_KNOWN_FORMAT_GET_CLASS(format)->get_key(format);
+ result = class->get_key(format);
+
+ //assert(result != NULL);
return result;
@@ -274,8 +288,13 @@ char *g_known_format_get_key(const GKnownFormat *format)
char *g_known_format_get_description(const GKnownFormat *format)
{
char *result; /* Description à retourner */
+ GKnownFormatClass *class; /* Classe de l'instance */
+
+ class = G_KNOWN_FORMAT_GET_CLASS(format);
+
+ result = class->get_desc(format);
- result = G_KNOWN_FORMAT_GET_CLASS(format)->get_desc(format);
+ //assert(result != NULL);
return result;
@@ -285,8 +304,6 @@ char *g_known_format_get_description(const GKnownFormat *format)
/******************************************************************************
* *
* Paramètres : format = format chargé dont l'analyse est lancée. *
-* gid = groupe de travail dédié. *
-* status = barre de statut à tenir informée. *
* *
* Description : Assure l'interprétation d'un format en différé. *
* *
@@ -296,60 +313,30 @@ char *g_known_format_get_description(const GKnownFormat *format)
* *
******************************************************************************/
-bool g_known_format_analyze(GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+bool g_known_format_analyze(GKnownFormat *format)
{
bool result; /* Bilan à retourner */
GKnownFormatClass *class; /* Classe de l'instance */
- handle_known_format_analysis(PGA_FORMAT_ANALYSIS_STARTED, format, gid, status);
+ //handle_known_format_analysis(PGA_FORMAT_ANALYSIS_STARTED, format, gid, status);
class = G_KNOWN_FORMAT_GET_CLASS(format);
- result = class->analyze(format, gid, status);
+ result = class->analyze(format);
- handle_known_format_analysis(PGA_FORMAT_ANALYSIS_ENDED, format, gid, status);
+ //handle_known_format_analysis(PGA_FORMAT_ANALYSIS_ENDED, format, gid, status);
return result;
}
-/******************************************************************************
-* *
-* Paramètres : format = description de l'exécutable à manipuler. *
-* gid = groupe de travail dédié. *
-* status = barre de statut à tenir informée. *
-* *
-* Description : Réalise un traitement post-désassemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_known_format_complete_analysis(GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status)
-{
- GKnownFormatClass *class; /* Classe de l'instance */
-
- handle_known_format_analysis(PGA_FORMAT_POST_ANALYSIS_STARTED, format, gid, status);
-
- class = G_KNOWN_FORMAT_GET_CLASS(format);
-
- if (class->complete != NULL)
- class->complete(format, gid, status);
-
- handle_known_format_analysis(PGA_FORMAT_POST_ANALYSIS_ENDED, format, gid, status);
-
-}
-
-
/* ---------------------------------------------------------------------------------- */
/* CONSERVATION ET RECHARGEMENT DES DONNEES */
/* ---------------------------------------------------------------------------------- */
-
+#if 0
/******************************************************************************
* *
* Paramètres : operand = élément GLib à constuire. *
@@ -468,3 +455,4 @@ static bool g_known_format_store(GKnownFormat *format, GObjectStorage *storage,
return result;
}
+#endif
diff --git a/src/format/known.h b/src/format/known.h
index dcc8669..41236df 100644
--- a/src/format/known.h
+++ b/src/format/known.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* format.h - prototypes pour le support des différents formats binaires reconnus
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,37 +25,17 @@
#define _FORMAT_KNOWN_H
-#include <glib-object.h>
-#include <stdbool.h>
-
-
#include "../analysis/content.h"
-#include "../glibext/delayed.h"
-#include "../glibext/notifier.h"
-
+#include "../glibext/helpers.h"
-#define G_TYPE_KNOWN_FORMAT g_known_format_get_type()
-#define G_KNOWN_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KNOWN_FORMAT, GKnownFormat))
-#define G_IS_KNOWN_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KNOWN_FORMAT))
-#define G_KNOWN_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KNOWN_FORMAT, GKnownFormatClass))
-#define G_IS_KNOWN_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KNOWN_FORMAT))
-#define G_KNOWN_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KNOWN_FORMAT, GKnownFormatClass))
+#define G_TYPE_KNOWN_FORMAT (g_known_format_get_type())
-/* Format binaire générique (instance) */
-typedef struct _GKnownFormat GKnownFormat;
+DECLARE_GTYPE(GKnownFormat, g_known_format, G, KNOWN_FORMAT);
-/* Format binaire générique (classe) */
-typedef struct _GKnownFormatClass GKnownFormatClass;
-/* Indique le type défini pour un format binaire générique. */
-GType g_known_format_get_type(void);
-
-/* Définit le contenu binaire à analyser. */
-void g_known_format_set_content(GKnownFormat *, GBinContent *);
-
/* Fournit une référence vers le contenu binaire analysé. */
GBinContent *g_known_format_get_content(const GKnownFormat *);
@@ -66,10 +46,7 @@ char *g_known_format_get_key(const GKnownFormat *);
char *g_known_format_get_description(const GKnownFormat *);
/* Assure l'interprétation d'un format en différé. */
-bool g_known_format_analyze(GKnownFormat *, wgroup_id_t, GtkStatusStack *);
-
-/* Réalise un traitement post-désassemblage. */
-void g_known_format_complete_analysis(GKnownFormat *, wgroup_id_t, GtkStatusStack *);
+bool g_known_format_analyze(GKnownFormat *);
diff --git a/src/format/format-int.h b/src/format/program-int.h
index f18bb24..8464fe4 100644
--- a/src/format/format-int.h
+++ b/src/format/program-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * format-int.h - prototypes utiles aux formats binaires
+ * program-int.h - prototypes internes pour le support des différents formats de programmes
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,14 +21,59 @@
*/
-#ifndef _FORMAT_FORMAT_INT_H
-#define _FORMAT_FORMAT_INT_H
+#ifndef _FORMAT_PROGRAM_INT_H
+#define _FORMAT_PROGRAM_INT_H
-#include "format.h"
+#include "program.h"
#include "known-int.h"
+
+
+
+/* Indique le boutisme employé par le format binaire analysé. */
+typedef SourceEndian (* program_get_endian_fc) (const GProgramFormat *);
+
+/* Fournit l'emplacement d'une section donnée. */
+typedef bool (* find_range_by_name_fc) (const GProgramFormat *, const char *, mrange_t *);
+
+
+/* Format de programme générique (instance) */
+struct _GProgramFormat
+{
+ GKnownFormat parent; /* A laisser en premier */
+
+};
+
+/* Format de programme générique (classe) */
+struct _GProgramFormatClass
+{
+ GKnownFormatClass parent; /* A laisser en premier */
+
+ program_get_endian_fc get_endian; /* Boutisme employé */
+ find_range_by_name_fc find_range_by_name; /* Emplacement de sections */
+
+};
+
+
+/* Met en place un nouveau contenu binaire à analyser. */
+bool g_program_format_create(GProgramFormat *, GBinContent *);
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
#include "preload.h"
#include "../glibext/objhole.h"
#include "../mangling/demangler.h"
@@ -38,9 +83,6 @@
/* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */
-/* Indique le boutisme employé par le format binaire analysé. */
-typedef SourceEndian (* format_get_endian_fc) (const GBinFormat *);
-
/* Rythme des allocations pour les entrées de code */
#define EXTRA_POINT_BLOCK 20
@@ -120,8 +162,6 @@ struct _GBinFormatClass
{
GKnownFormatClass parent; /* A laisser en premier */
- format_get_endian_fc get_endian; /* Boutisme employé */
-
/* Signaux */
void (* symbol_added) (GBinFormat *, GBinSymbol *);
@@ -156,5 +196,8 @@ GDataType *g_binary_format_decode_type(const GBinFormat *, const char *);
GBinRoutine *g_binary_format_decode_routine(const GBinFormat *, const char *);
+#endif
+
+
-#endif /* _FORMAT_FORMAT_INT_H */
+#endif /* _FORMAT_PROGRAM_INT_H */
diff --git a/src/format/format.c b/src/format/program.c
index d126236..9b9df81 100644
--- a/src/format/format.c
+++ b/src/format/program.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * format.c - support des différents formats binaires
+ * program.c - support des différents formats de programmes
*
- * Copyright (C) 2009-2020 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,40 +21,45 @@
*/
-#include "format.h"
+#include "program.h"
-#include <assert.h>
-#include <malloc.h>
-#include <string.h>
+//#include <assert.h>
+//#include <malloc.h>
+//#include <string.h>
-#include "format-int.h"
+#include "program-int.h"
+
+/*
#include "preload.h"
#include "../arch/processor.h"
#include "../common/sort.h"
#include "../core/demanglers.h"
#include "../plugins/pglist.h"
+*/
/* Initialise la classe des formats binaires génériques. */
-static void g_binary_format_class_init(GBinFormatClass *);
+static void g_program_format_class_init(GProgramFormatClass *);
/* Initialise une instance de format binaire générique. */
-static void g_binary_format_init(GBinFormat *);
+static void g_program_format_init(GProgramFormat *);
/* Supprime toutes les références externes. */
-static void g_binary_format_dispose(GBinFormat *);
+static void g_program_format_dispose(GProgramFormat *);
/* Procède à la libération totale de la mémoire. */
-static void g_binary_format_finalize(GBinFormat *);
+static void g_program_format_finalize(GProgramFormat *);
+
+#if 0
/* Charge les plages de couvertures depuis une mémoire tampon. */
-static bool g_binary_format_load_start_points(GBinFormat *, packed_buffer_t *);
+static bool g_program_format_load_start_points(GProgramFormat *, packed_buffer_t *);
/* Sauvegarde les points de départ enregistrés pour un format. */
-static bool g_binary_format_store_start_points(GBinFormat *, packed_buffer_t *);
+static bool g_program_format_store_start_points(GProgramFormat *, packed_buffer_t *);
@@ -62,13 +67,13 @@ static bool g_binary_format_store_start_points(GBinFormat *, packed_buffer_t *);
/* Retire un symbole de la collection du format binaire. */
-static void _g_binary_format_remove_symbol(GBinFormat *, size_t);
+static void _g_program_format_remove_symbol(GProgramFormat *, size_t);
/* Recherche le symbole associé à une adresse. */
-static bool _g_binary_format_find_symbol(const GBinFormat *, const vmpa2t *, __compar_fn_t, size_t *, GBinSymbol **);
+static bool _g_program_format_find_symbol(const GProgramFormat *, const vmpa2t *, __compar_fn_t, size_t *, GBinSymbol **);
/* Recherche un symbole particulier. */
-static bool __g_binary_format_find_symbol(const GBinFormat *, const void *, __compar_fn_t, size_t *, GBinSymbol **);
+static bool __g_program_format_find_symbol(const GProgramFormat *, const void *, __compar_fn_t, size_t *, GBinSymbol **);
@@ -76,10 +81,10 @@ static bool __g_binary_format_find_symbol(const GBinFormat *, const void *, __co
/* Charge les erreurs de chargement depuis une mémoire tampon. */
-static bool g_binary_format_load_errors(GBinFormat *, packed_buffer_t *);
+static bool g_program_format_load_errors(GProgramFormat *, packed_buffer_t *);
/* Sauvegarde les erreurs de chargement dans une mémoire tampon. */
-static bool g_binary_format_store_errors(GBinFormat *, packed_buffer_t *);
+static bool g_program_format_store_errors(GProgramFormat *, packed_buffer_t *);
@@ -87,17 +92,18 @@ static bool g_binary_format_store_errors(GBinFormat *, packed_buffer_t *);
/* Charge un format depuis une mémoire tampon. */
-static bool g_binary_format_load(GBinFormat *, GObjectStorage *, packed_buffer_t *);
+static bool g_program_format_load(GProgramFormat *, GObjectStorage *, packed_buffer_t *);
/* Sauvegarde un format dans une mémoire tampon. */
-static bool g_binary_format_store(GBinFormat *, GObjectStorage *, packed_buffer_t *);
+static bool g_program_format_store(GProgramFormat *, GObjectStorage *, packed_buffer_t *);
+#endif
/* Indique le type défini pour un format binaire générique. */
-G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_KNOWN_FORMAT);
+G_DEFINE_TYPE(GProgramFormat, g_program_format, G_TYPE_KNOWN_FORMAT);
/******************************************************************************
@@ -112,25 +118,27 @@ G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_KNOWN_FORMAT);
* *
******************************************************************************/
-static void g_binary_format_class_init(GBinFormatClass *klass)
+static void g_program_format_class_init(GProgramFormatClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GKnownFormatClass *known; /* Version de classe parente */
+ //GKnownFormatClass *known; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_format_dispose;
- object->finalize = (GObjectFinalizeFunc)g_binary_format_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_program_format_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_program_format_finalize;
+
+#if 0
known = G_KNOWN_FORMAT_CLASS(klass);
- known->load = (load_known_fc)g_binary_format_load;
- known->store = (load_known_fc)g_binary_format_store;
+ known->load = (load_known_fc)g_program_format_load;
+ known->store = (load_known_fc)g_program_format_store;
g_signal_new("symbol-added",
G_TYPE_BIN_FORMAT,
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GBinFormatClass, symbol_added),
+ G_STRUCT_OFFSET(GProgramFormatClass, symbol_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT);
@@ -138,11 +146,13 @@ static void g_binary_format_class_init(GBinFormatClass *klass)
g_signal_new("symbol-removed",
G_TYPE_BIN_FORMAT,
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GBinFormatClass, symbol_removed),
+ G_STRUCT_OFFSET(GProgramFormatClass, symbol_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT);
+#endif
+
}
@@ -158,8 +168,10 @@ static void g_binary_format_class_init(GBinFormatClass *klass)
* *
******************************************************************************/
-static void g_binary_format_init(GBinFormat *format)
+static void g_program_format_init(GProgramFormat *format)
{
+
+#if 0
fmt_extra_data_t *extra; /* Données insérées à modifier */
extra = GET_BIN_FORMAT_EXTRA(format);
@@ -184,6 +196,8 @@ static void g_binary_format_init(GBinFormat *format)
g_atomic_int_set(&format->error_locked, 0);
#endif
+#endif
+
}
@@ -199,8 +213,10 @@ static void g_binary_format_init(GBinFormat *format)
* *
******************************************************************************/
-static void g_binary_format_dispose(GBinFormat *format)
+static void g_program_format_dispose(GProgramFormat *format)
{
+#if 0
+
size_t i; /* Boucle de parcours */
g_rw_lock_clear(&format->pt_lock);
@@ -216,7 +232,10 @@ static void g_binary_format_dispose(GBinFormat *format)
g_mutex_clear(&format->error_mutex);
- G_OBJECT_CLASS(g_binary_format_parent_class)->dispose(G_OBJECT(format));
+#endif
+
+
+ G_OBJECT_CLASS(g_program_format_parent_class)->dispose(G_OBJECT(format));
}
@@ -233,8 +252,10 @@ static void g_binary_format_dispose(GBinFormat *format)
* *
******************************************************************************/
-static void g_binary_format_finalize(GBinFormat *format)
+static void g_program_format_finalize(GProgramFormat *format)
{
+#if 0
+
DisassPriorityLevel i; /* Boucle de parcours #1 */
size_t k; /* Boucle de parcours #2 */
@@ -255,13 +276,43 @@ static void g_binary_format_finalize(GBinFormat *format)
}
- G_OBJECT_CLASS(g_binary_format_parent_class)->finalize(G_OBJECT(format));
+#endif
+
+
+
+ G_OBJECT_CLASS(g_program_format_parent_class)->finalize(G_OBJECT(format));
}
/******************************************************************************
* *
+* Paramètres : format = description du format à initialiser pleinement. *
+* content = contenu binaire à parcourir. *
+* *
+* Description : Met en place un nouveau contenu binaire à analyser. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_program_format_create(GProgramFormat *format, GBinContent *content)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_known_format_create(G_KNOWN_FORMAT(format), content);
+
+ return result;
+
+}
+
+
+#if 0
+
+/******************************************************************************
+* *
* Paramètres : format = format à venir modifier. *
* flag = drapeau d'information complémentaire à planter. *
* *
@@ -273,7 +324,7 @@ static void g_binary_format_finalize(GBinFormat *format)
* *
******************************************************************************/
-bool g_binary_format_set_flag(GBinFormat *format, FormatFlag flag)
+bool g_program_format_set_flag(GProgramFormat *format, FormatFlag flag)
{
bool result; /* Bilan à retourner */
fmt_extra_data_t *extra; /* Données insérées à modifier */
@@ -306,7 +357,7 @@ bool g_binary_format_set_flag(GBinFormat *format, FormatFlag flag)
* *
******************************************************************************/
-bool g_binary_format_unset_flag(GBinFormat *format, FormatFlag flag)
+bool g_program_format_unset_flag(GProgramFormat *format, FormatFlag flag)
{
bool result; /* Bilan à retourner */
fmt_extra_data_t *extra; /* Données insérées à modifier */
@@ -339,7 +390,7 @@ bool g_binary_format_unset_flag(GBinFormat *format, FormatFlag flag)
* *
******************************************************************************/
-bool g_binary_format_has_flag(const GBinFormat *format, FormatFlag flag)
+bool g_program_format_has_flag(const GProgramFormat *format, FormatFlag flag)
{
bool result; /* Bilan à retourner */
fmt_extra_data_t *extra; /* Données insérées à modifier */
@@ -369,7 +420,7 @@ bool g_binary_format_has_flag(const GBinFormat *format, FormatFlag flag)
* *
******************************************************************************/
-FormatFlag g_binary_format_get_flags(const GBinFormat *format)
+FormatFlag g_program_format_get_flags(const GProgramFormat *format)
{
FormatFlag result; /* Fanions à retourner */
fmt_extra_data_t *extra; /* Données insérées à modifier */
@@ -386,6 +437,8 @@ FormatFlag g_binary_format_get_flags(const GBinFormat *format)
}
+#endif
+
/******************************************************************************
* *
@@ -399,11 +452,14 @@ FormatFlag g_binary_format_get_flags(const GBinFormat *format)
* *
******************************************************************************/
-SourceEndian g_binary_format_get_endianness(const GBinFormat *format)
+SourceEndian g_program_format_get_endianness(const GProgramFormat *format)
{
SourceEndian result; /* Boutisme à retourner */
+ GProgramFormatClass *class; /* Classe de l'instance */
+
+ class = G_PROGRAM_FORMAT_GET_CLASS(format);
- result = G_BIN_FORMAT_GET_CLASS(format)->get_endian(format);
+ result = class->get_endian(format);
return result;
@@ -412,6 +468,40 @@ SourceEndian g_binary_format_get_endianness(const GBinFormat *format)
/******************************************************************************
* *
+* Paramètres : format = description du programme à consulter. *
+* name = nom de la section recherchée. *
+* range = emplacement en mémoire à renseigner. [OUT] *
+* *
+* Description : Fournit l'emplacement d'une section donnée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_program_format_find_section_range_by_name(const GProgramFormat *format, const char *name, mrange_t *range)
+{
+ bool result; /* Bilan à retourner */
+ GProgramFormatClass *class; /* Classe de l'instance */
+
+ class = G_PROGRAM_FORMAT_GET_CLASS(format);
+
+ if (class->find_range_by_name == NULL)
+ result = false;
+
+ else
+ result = class->find_range_by_name(format, name, range);
+
+ return result;
+
+}
+
+
+#if 0
+
+/******************************************************************************
+* *
* Paramètres : format = description de l'exécutable à compléter. *
* pt = point de l'espace mémoire à considérer. *
* level = indication de priorité et d'origine de l'adresse. *
@@ -424,7 +514,7 @@ SourceEndian g_binary_format_get_endianness(const GBinFormat *format)
* *
******************************************************************************/
-void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, DisassPriorityLevel level)
+void g_program_format_register_code_point(GProgramFormat *format, virt_t pt, DisassPriorityLevel level)
{
assert(level < DPL_COUNT);
@@ -459,7 +549,7 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, DisassPr
* *
******************************************************************************/
-static bool g_binary_format_load_start_points(GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_program_format_load_start_points(GProgramFormat *format, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
DisassPriorityLevel i; /* Boucle de parcours #1 */
@@ -512,7 +602,7 @@ static bool g_binary_format_load_start_points(GBinFormat *format, packed_buffer_
* *
******************************************************************************/
-static bool g_binary_format_store_start_points(GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_program_format_store_start_points(GProgramFormat *format, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
DisassPriorityLevel i; /* Boucle de parcours #1 */
@@ -555,7 +645,7 @@ static bool g_binary_format_store_start_points(GBinFormat *format, packed_buffer
* *
******************************************************************************/
-void g_binary_format_preload_disassembling_context(GBinFormat *format, GProcContext *ctx, GtkStatusStack *status)
+void g_program_format_preload_disassembling_context(GProgramFormat *format, GProcContext *ctx, GtkStatusStack *status)
{
g_preload_info_copy(format->info, G_PRELOAD_INFO(ctx));
@@ -576,7 +666,7 @@ void g_binary_format_preload_disassembling_context(GBinFormat *format, GProcCont
* *
******************************************************************************/
-void g_binary_format_activate_disassembling_context(GBinFormat *format, GProcContext *ctx, GtkStatusStack *status)
+void g_program_format_activate_disassembling_context(GProgramFormat *format, GProcContext *ctx, GtkStatusStack *status)
{
DisassPriorityLevel i; /* Boucle de parcours #1 */
size_t k; /* Boucle de parcours #2 */
@@ -610,7 +700,7 @@ void g_binary_format_activate_disassembling_context(GBinFormat *format, GProcCon
* *
******************************************************************************/
-GCompDemangler *g_binary_format_get_demangler(const GBinFormat *format)
+GCompDemangler *g_program_format_get_demangler(const GProgramFormat *format)
{
GCompDemangler *result; /* Décodeur à retourner */
@@ -637,7 +727,7 @@ GCompDemangler *g_binary_format_get_demangler(const GBinFormat *format)
* *
******************************************************************************/
-GDataType *g_binary_format_decode_type(const GBinFormat *format, const char *desc)
+GDataType *g_program_format_decode_type(const GProgramFormat *format, const char *desc)
{
GDataType *result; /* Construction à remonter */
GCompDemangler *demangler; /* Accès plus lisible */
@@ -667,7 +757,7 @@ GDataType *g_binary_format_decode_type(const GBinFormat *format, const char *des
* *
******************************************************************************/
-GBinRoutine *g_binary_format_decode_routine(const GBinFormat *format, const char *desc)
+GBinRoutine *g_program_format_decode_routine(const GProgramFormat *format, const char *desc)
{
GBinRoutine *result; /* Construction à remonter */
GCompDemangler *demangler; /* Accès plus lisible */
@@ -708,7 +798,7 @@ GBinRoutine *g_binary_format_decode_routine(const GBinFormat *format, const char
* *
******************************************************************************/
-void g_binary_format_lock_unlock_symbols_rd(GBinFormat *format, bool state)
+void g_program_format_lock_unlock_symbols_rd(GProgramFormat *format, bool state)
{
#ifndef NDEBUG
gint test; /* Test de valeur courante */
@@ -746,7 +836,7 @@ void g_binary_format_lock_unlock_symbols_rd(GBinFormat *format, bool state)
* *
******************************************************************************/
-void g_binary_format_lock_unlock_symbols_wr(GBinFormat *format, bool state)
+void g_program_format_lock_unlock_symbols_wr(GProgramFormat *format, bool state)
{
if (state)
{
@@ -778,7 +868,7 @@ void g_binary_format_lock_unlock_symbols_wr(GBinFormat *format, bool state)
* *
******************************************************************************/
#ifndef NDEBUG
-void g_binary_format_check_for_symbols_lock(const GBinFormat *format)
+void g_program_format_check_for_symbols_lock(const GProgramFormat *format)
{
assert(g_atomic_int_get(&format->sym_locked) > 0);
@@ -798,7 +888,7 @@ void g_binary_format_check_for_symbols_lock(const GBinFormat *format)
* *
******************************************************************************/
-unsigned int g_binary_format_get_symbols_stamp(const GBinFormat *format)
+unsigned int g_program_format_get_symbols_stamp(const GProgramFormat *format)
{
return format->sym_stamp;
@@ -817,7 +907,7 @@ unsigned int g_binary_format_get_symbols_stamp(const GBinFormat *format)
* *
******************************************************************************/
-size_t g_binary_format_count_symbols(const GBinFormat *format)
+size_t g_program_format_count_symbols(const GProgramFormat *format)
{
assert(g_atomic_int_get(&format->sym_locked) > 0);
@@ -839,7 +929,7 @@ size_t g_binary_format_count_symbols(const GBinFormat *format)
* *
******************************************************************************/
-GBinSymbol *g_binary_format_get_symbol(const GBinFormat *format, size_t index)
+GBinSymbol *g_program_format_get_symbol(const GProgramFormat *format, size_t index)
{
GBinSymbol *result; /* Symbole à retourner */
@@ -877,7 +967,7 @@ GBinSymbol *g_binary_format_get_symbol(const GBinFormat *format, size_t index)
* *
******************************************************************************/
-bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
+bool g_program_format_add_symbol(GProgramFormat *format, GBinSymbol *symbol)
{
bool result; /* Statut d'ajout à retourner */
#ifndef NDEBUG
@@ -887,7 +977,7 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
size_t index; /* Indice du point d'insertion */
/**
- * Pour que les fonctions de recherche basées sur _g_binary_format_find_symbol()
+ * Pour que les fonctions de recherche basées sur _g_program_format_find_symbol()
* fassent bien leur office, il faut que les symboles soient triés.
*
* Cependant, les localisations à satisfaire lors d'une recherche recontrent
@@ -912,7 +1002,7 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
assert(has_phys_addr(addr) || g_binary_symbol_get_status(symbol) == SSS_DYNAMIC);
#endif
- g_binary_format_lock_unlock_symbols_wr(format, true);
+ g_program_format_lock_unlock_symbols_wr(format, true);
/**
* Avec tous les traitements parallèles, il est possible que plusieurs chemins d'exécution
@@ -939,7 +1029,7 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
else
g_object_unref(G_OBJECT(symbol));
- g_binary_format_lock_unlock_symbols_wr(format, false);
+ g_program_format_lock_unlock_symbols_wr(format, false);
if (result)
g_signal_emit_by_name(format, "symbol-added", symbol);
@@ -963,7 +1053,7 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
* *
******************************************************************************/
-bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_t count)
+bool g_program_format_add_symbols(GProgramFormat *format, GBinSymbol **symbols, size_t count)
{
bool result; /* Statut d'ajout à retourner */
#ifndef NDEBUG
@@ -977,7 +1067,7 @@ bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_
size_t index; /* Indice du point d'insertion */
/**
- * Pour que les fonctions de recherche basées sur _g_binary_format_find_symbol()
+ * Pour que les fonctions de recherche basées sur _g_program_format_find_symbol()
* fassent bien leur office, il faut que les symboles soient triés.
*
* Cependant, les localisations à satisfaire lors d'une recherche recontrent
@@ -1014,7 +1104,7 @@ bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_
}
#endif
- g_binary_format_lock_unlock_symbols_wr(format, true);
+ g_program_format_lock_unlock_symbols_wr(format, true);
/**
* Avec tous les traitements parallèles, il est possible que plusieurs chemins d'exécution
@@ -1042,7 +1132,7 @@ bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_
}
- g_binary_format_lock_unlock_symbols_wr(format, false);
+ g_program_format_lock_unlock_symbols_wr(format, false);
if (result)
for (i = 0; i < count; i++)
@@ -1066,7 +1156,7 @@ bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_
* *
******************************************************************************/
-static void _g_binary_format_remove_symbol(GBinFormat *format, size_t index)
+static void _g_program_format_remove_symbol(GProgramFormat *format, size_t index)
{
assert(g_atomic_int_get(&format->sym_locked) == 1);
@@ -1096,22 +1186,22 @@ static void _g_binary_format_remove_symbol(GBinFormat *format, size_t index)
* *
******************************************************************************/
-void g_binary_format_remove_symbol(GBinFormat *format, GBinSymbol *symbol)
+void g_program_format_remove_symbol(GProgramFormat *format, GBinSymbol *symbol)
{
bool found; /* Jeton de présence */
size_t index; /* Indice du point de retrait */
g_object_ref(G_OBJECT(symbol));
- g_binary_format_lock_unlock_symbols_wr(format, true);
+ g_program_format_lock_unlock_symbols_wr(format, true);
found = bsearch_index(&symbol, format->symbols, format->sym_count,
sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp, &index);
if (found)
- _g_binary_format_remove_symbol(format, index);
+ _g_program_format_remove_symbol(format, index);
- g_binary_format_lock_unlock_symbols_wr(format, false);
+ g_program_format_lock_unlock_symbols_wr(format, false);
if (found)
g_signal_emit_by_name(format, "symbol-removed", symbol);
@@ -1135,7 +1225,7 @@ void g_binary_format_remove_symbol(GBinFormat *format, GBinSymbol *symbol)
* *
******************************************************************************/
-bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label, GBinSymbol **symbol)
+bool g_program_format_find_symbol_by_label(GProgramFormat *format, const char *label, GBinSymbol **symbol)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
@@ -1143,7 +1233,7 @@ bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label,
result = false;
- g_binary_format_lock_symbols_rd(format);
+ g_program_format_lock_symbols_rd(format);
for (i = 0; i < format->sym_count && !result; i++)
{
@@ -1163,7 +1253,7 @@ bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label,
}
- g_binary_format_unlock_symbols_rd(format);
+ g_program_format_unlock_symbols_rd(format);
return result;
@@ -1186,16 +1276,16 @@ bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label,
* *
******************************************************************************/
-static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t *addr, __compar_fn_t fn, size_t *index, GBinSymbol **symbol)
+static bool _g_program_format_find_symbol(const GProgramFormat *format, const vmpa2t *addr, __compar_fn_t fn, size_t *index, GBinSymbol **symbol)
{
/**
* Pour ce qui est des justifications quant à la vérification suivante,
- * se référer aux commentaires placés dans g_binary_format_add_symbol().
+ * se référer aux commentaires placés dans g_program_format_add_symbol().
*/
assert(has_phys_addr(addr));
- return __g_binary_format_find_symbol(format, addr, fn, index, symbol);
+ return __g_program_format_find_symbol(format, addr, fn, index, symbol);
}
@@ -1216,7 +1306,7 @@ static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t
* *
******************************************************************************/
-static bool __g_binary_format_find_symbol(const GBinFormat *format, const void *key, __compar_fn_t fn, size_t *index, GBinSymbol **symbol)
+static bool __g_program_format_find_symbol(const GProgramFormat *format, const void *key, __compar_fn_t fn, size_t *index, GBinSymbol **symbol)
{
bool result; /* Bilan à retourner */
void *found; /* Résultat de recherches */
@@ -1268,7 +1358,7 @@ static bool __g_binary_format_find_symbol(const GBinFormat *format, const void *
* *
******************************************************************************/
-bool g_binary_format_find_symbol_index_at(GBinFormat *format, const vmpa2t *addr, size_t *index)
+bool g_program_format_find_symbol_index_at(GProgramFormat *format, const vmpa2t *addr, size_t *index)
{
bool result; /* Bilan à retourner */
@@ -1282,11 +1372,11 @@ bool g_binary_format_find_symbol_index_at(GBinFormat *format, const vmpa2t *addr
}
- g_binary_format_lock_symbols_rd(format);
+ g_program_format_lock_symbols_rd(format);
- result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, index, NULL);
+ result = _g_program_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, index, NULL);
- g_binary_format_unlock_symbols_rd(format);
+ g_program_format_unlock_symbols_rd(format);
return result;
@@ -1307,7 +1397,7 @@ bool g_binary_format_find_symbol_index_at(GBinFormat *format, const vmpa2t *addr
* *
******************************************************************************/
-bool g_binary_format_find_symbol_at(GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+bool g_program_format_find_symbol_at(GProgramFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
{
bool result; /* Bilan à retourner */
@@ -1321,11 +1411,11 @@ bool g_binary_format_find_symbol_at(GBinFormat *format, const vmpa2t *addr, GBin
}
- g_binary_format_lock_symbols_rd(format);
+ g_program_format_lock_symbols_rd(format);
- result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, NULL, symbol);
+ result = _g_program_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, NULL, symbol);
- g_binary_format_unlock_symbols_rd(format);
+ g_program_format_unlock_symbols_rd(format);
return result;
@@ -1346,7 +1436,7 @@ bool g_binary_format_find_symbol_at(GBinFormat *format, const vmpa2t *addr, GBin
* *
******************************************************************************/
-bool g_binary_format_find_symbol_for(GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+bool g_program_format_find_symbol_for(GProgramFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
{
bool result; /* Bilan à retourner */
@@ -1360,11 +1450,11 @@ bool g_binary_format_find_symbol_for(GBinFormat *format, const vmpa2t *addr, GBi
}
- g_binary_format_lock_symbols_rd(format);
+ g_program_format_lock_symbols_rd(format);
- result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, NULL, symbol);
+ result = _g_program_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, NULL, symbol);
- g_binary_format_unlock_symbols_rd(format);
+ g_program_format_unlock_symbols_rd(format);
return result;
@@ -1385,7 +1475,7 @@ bool g_binary_format_find_symbol_for(GBinFormat *format, const vmpa2t *addr, GBi
* *
******************************************************************************/
-bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+bool g_program_format_find_next_symbol_at(GProgramFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
{
bool result; /* Bilan à retourner */
size_t index; /* Indice à considérer */
@@ -1400,9 +1490,9 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr,
}
- g_binary_format_lock_symbols_rd(format);
+ g_program_format_lock_symbols_rd(format);
- result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, &index, NULL);
+ result = _g_program_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, &index, NULL);
if (result && (index + 1) < format->sym_count)
{
@@ -1417,7 +1507,7 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr,
result = false;
}
- g_binary_format_unlock_symbols_rd(format);
+ g_program_format_unlock_symbols_rd(format);
return result;
@@ -1438,7 +1528,7 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr,
* *
******************************************************************************/
-bool g_binary_format_find_first_symbol_inside(GBinFormat *format, const mrange_t *range, size_t *index)
+bool g_program_format_find_first_symbol_inside(GProgramFormat *format, const mrange_t *range, size_t *index)
{
bool result; /* Bilan à retourner */
const GBinSymbol *prev; /* Symbole précédent */
@@ -1463,7 +1553,7 @@ bool g_binary_format_find_first_symbol_inside(GBinFormat *format, const mrange_t
g_rw_lock_reader_lock(&format->syms_lock);
- result = __g_binary_format_find_symbol(format, range, (__compar_fn_t)find_symbol, index, NULL);
+ result = __g_program_format_find_symbol(format, range, (__compar_fn_t)find_symbol, index, NULL);
if (result)
while (*index > 0)
@@ -1502,15 +1592,15 @@ bool g_binary_format_find_first_symbol_inside(GBinFormat *format, const mrange_t
* *
******************************************************************************/
-bool g_binary_format_resolve_symbol(GBinFormat *format, const vmpa2t *addr, bool strict, GBinSymbol **symbol, phys_t *diff)
+bool g_program_format_resolve_symbol(GProgramFormat *format, const vmpa2t *addr, bool strict, GBinSymbol **symbol, phys_t *diff)
{
bool result; /* Bilan à retourner */
const mrange_t *range; /* Espace mémoire parcouru */
if (strict)
- result = g_binary_format_find_symbol_at(format, addr, symbol);
+ result = g_program_format_find_symbol_at(format, addr, symbol);
else
- result = g_binary_format_find_symbol_for(format, addr, symbol);
+ result = g_program_format_find_symbol_for(format, addr, symbol);
if (result)
{
@@ -1548,7 +1638,7 @@ bool g_binary_format_resolve_symbol(GBinFormat *format, const vmpa2t *addr, bool
* *
******************************************************************************/
-void g_binary_format_lock_unlock_errors(GBinFormat *format, bool state)
+void g_program_format_lock_unlock_errors(GProgramFormat *format, bool state)
{
if (state)
{
@@ -1584,11 +1674,11 @@ void g_binary_format_lock_unlock_errors(GBinFormat *format, bool state)
* *
******************************************************************************/
-void g_binary_format_add_error(GBinFormat *format, BinaryFormatError type, const vmpa2t *addr, const char *desc)
+void g_program_format_add_error(GProgramFormat *format, BinaryFormatError type, const vmpa2t *addr, const char *desc)
{
fmt_error *error; /* Raccourci de confort */
- g_binary_format_lock_errors(format);
+ g_program_format_lock_errors(format);
format->errors = realloc(format->errors, ++format->error_count * sizeof(fmt_error));
@@ -1603,7 +1693,7 @@ void g_binary_format_add_error(GBinFormat *format, BinaryFormatError type, const
else
error->desc = NULL;
- g_binary_format_unlock_errors(format);
+ g_program_format_unlock_errors(format);
}
@@ -1620,7 +1710,7 @@ void g_binary_format_add_error(GBinFormat *format, BinaryFormatError type, const
* *
******************************************************************************/
-size_t g_binary_format_count_errors(GBinFormat *format)
+size_t g_program_format_count_errors(GProgramFormat *format)
{
size_t result; /* Quantité à retourner */
@@ -1649,7 +1739,7 @@ size_t g_binary_format_count_errors(GBinFormat *format)
* *
******************************************************************************/
-bool g_binary_format_get_error(GBinFormat *format, size_t index, BinaryFormatError *type, vmpa2t *addr, char **desc)
+bool g_program_format_get_error(GProgramFormat *format, size_t index, BinaryFormatError *type, vmpa2t *addr, char **desc)
{
bool result; /* Bilan à retourner */
fmt_error *error; /* Raccourci de confort */
@@ -1693,7 +1783,7 @@ bool g_binary_format_get_error(GBinFormat *format, size_t index, BinaryFormatErr
* *
******************************************************************************/
-static bool g_binary_format_load_errors(GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_program_format_load_errors(GProgramFormat *format, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
uleb128_t value; /* Valeur ULEB128 à charger */
@@ -1701,7 +1791,7 @@ static bool g_binary_format_load_errors(GBinFormat *format, packed_buffer_t *pbu
fmt_error *error; /* Raccourci de confort */
rle_string str; /* Chaîne à charger */
- g_binary_format_lock_errors(format);
+ g_program_format_lock_errors(format);
result = unpack_uleb128(&value, pbuf);
if (!result) goto exit;
@@ -1736,7 +1826,7 @@ static bool g_binary_format_load_errors(GBinFormat *format, packed_buffer_t *pbu
exit:
- g_binary_format_unlock_errors(format);
+ g_program_format_unlock_errors(format);
return result;
@@ -1756,14 +1846,14 @@ static bool g_binary_format_load_errors(GBinFormat *format, packed_buffer_t *pbu
* *
******************************************************************************/
-static bool g_binary_format_store_errors(GBinFormat *format, packed_buffer_t *pbuf)
+static bool g_program_format_store_errors(GProgramFormat *format, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
fmt_error *error; /* Raccourci de confort */
rle_string str; /* Chaîne à conserver */
- g_binary_format_lock_errors(format);
+ g_program_format_lock_errors(format);
result = pack_uleb128((uleb128_t []){ format->error_count }, pbuf);
@@ -1785,7 +1875,7 @@ static bool g_binary_format_store_errors(GBinFormat *format, packed_buffer_t *pb
}
- g_binary_format_unlock_errors(format);
+ g_program_format_unlock_errors(format);
return result;
@@ -1812,7 +1902,7 @@ static bool g_binary_format_store_errors(GBinFormat *format, packed_buffer_t *pb
* *
******************************************************************************/
-static bool g_binary_format_load(GBinFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_program_format_load(GProgramFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
fmt_extra_data_t *extra; /* Données insérées à consulter*/
@@ -1831,7 +1921,7 @@ static bool g_binary_format_load(GBinFormat *format, GObjectStorage *storage, pa
UNLOCK_GOBJECT_EXTRA(extra);
if (result)
- result = g_binary_format_load_start_points(format, pbuf);
+ result = g_program_format_load_start_points(format, pbuf);
if (result)
{
@@ -1857,7 +1947,7 @@ static bool g_binary_format_load(GBinFormat *format, GObjectStorage *storage, pa
if (result)
- result = g_binary_format_load_errors(format, pbuf);
+ result = g_program_format_load_errors(format, pbuf);
return result;
@@ -1878,7 +1968,7 @@ static bool g_binary_format_load(GBinFormat *format, GObjectStorage *storage, pa
* *
******************************************************************************/
-static bool g_binary_format_store(GBinFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_program_format_store(GProgramFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
{
bool result; /* Bilan à retourner */
fmt_extra_data_t *extra; /* Données insérées à consulter*/
@@ -1894,7 +1984,7 @@ static bool g_binary_format_store(GBinFormat *format, GObjectStorage *storage, p
UNLOCK_GOBJECT_EXTRA(extra);
if (result)
- result = g_binary_format_store_start_points(format, pbuf);
+ result = g_program_format_store_start_points(format, pbuf);
if (result)
{
@@ -1913,8 +2003,10 @@ static bool g_binary_format_store(GBinFormat *format, GObjectStorage *storage, p
if (result)
- result = g_binary_format_store_errors(format, pbuf);
+ result = g_program_format_store_errors(format, pbuf);
return result;
}
+
+#endif
diff --git a/src/format/format.h b/src/format/program.h
index f9aa430..12b095c 100644
--- a/src/format/format.h
+++ b/src/format/program.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * format.h - prototypes pour le support des différents formats binaires
+ * program.h - prototypes pour le support des différents formats de programmes
*
- * Copyright (C) 2009-2020 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,12 +21,35 @@
*/
-#ifndef _FORMAT_FORMAT_H
-#define _FORMAT_FORMAT_H
+#ifndef _FORMAT_PROGRAM_H
+#define _FORMAT_PROGRAM_H
-#include <glib-object.h>
#include <stdbool.h>
+
+
+#include "../arch/vmpa.h"
+#include "../common/datatypes.h"
+#include "../glibext/helpers.h"
+
+
+
+#define G_TYPE_PROGRAM_FORMAT (g_program_format_get_type())
+
+DECLARE_GTYPE(GProgramFormat, g_program_format, G, PROGRAM_FORMAT);
+
+
+/* Indique le boutisme employé par le format binaire analysé. */
+SourceEndian g_program_format_get_endianness(const GProgramFormat *);
+
+/* Fournit l'emplacement d'une section donnée. */
+bool g_program_format_find_section_range_by_name(const GProgramFormat *, const char *, mrange_t *);
+
+
+
+
+#if 0
+
#include <sys/types.h>
@@ -52,47 +75,31 @@ typedef enum _FormatFlag
} FormatFlag;
-#define G_TYPE_BIN_FORMAT g_binary_format_get_type()
-#define G_BIN_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BIN_FORMAT, GBinFormat))
-#define G_IS_BIN_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BIN_FORMAT))
-#define G_BIN_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_FORMAT, GBinFormatClass))
-#define G_IS_BIN_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_FORMAT))
-#define G_BIN_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_FORMAT, GBinFormatClass))
-/* Format binaire générique (instance) */
-typedef struct _GBinFormat GBinFormat;
-
-/* Format binaire générique (classe) */
-typedef struct _GBinFormatClass GBinFormatClass;
-
-
-/* Indique le type défini pour un format binaire générique. */
-GType g_binary_format_get_type(void);
-
/* Ajoute une information complémentaire à un format. */
-bool g_binary_format_set_flag(GBinFormat *, FormatFlag);
+bool g_program_format_set_flag(GProgramFormat *, FormatFlag);
/* Retire une information complémentaire à un format. */
-bool g_binary_format_unset_flag(GBinFormat *, FormatFlag);
+bool g_program_format_unset_flag(GProgramFormat *, FormatFlag);
/* Détermine si un format possède un fanion particulier. */
-bool g_binary_format_has_flag(const GBinFormat *, FormatFlag);
+bool g_program_format_has_flag(const GProgramFormat *, FormatFlag);
/* Fournit les particularités du format. */
-FormatFlag g_binary_format_get_flags(const GBinFormat *);
+FormatFlag g_program_format_get_flags(const GProgramFormat *);
/* Indique le boutisme employé par le format binaire analysé. */
-SourceEndian g_binary_format_get_endianness(const GBinFormat *);
+//SourceEndian g_program_format_get_endianness(const GProgramFormat *);
/* Enregistre une adresse comme début d'une zone de code. */
-void g_binary_format_register_code_point(GBinFormat *, virt_t, DisassPriorityLevel);
+void g_program_format_register_code_point(GProgramFormat *, virt_t, DisassPriorityLevel);
/* Intègre dans un contexte les informations tirées d'un format. */
-void g_binary_format_preload_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *);
+void g_program_format_preload_disassembling_context(GProgramFormat *, GProcContext *, GtkStatusStack *);
/* Définit les points de départ d'un contexte de désassemblage. */
-void g_binary_format_activate_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *);
+void g_program_format_activate_disassembling_context(GProgramFormat *, GProcContext *, GtkStatusStack *);
@@ -100,7 +107,7 @@ void g_binary_format_activate_disassembling_context(GBinFormat *, GProcContext *
/* Fournit le décodeur de symboles privilégié pour un format. */
-GCompDemangler *g_binary_format_get_demangler(const GBinFormat *);
+GCompDemangler *g_program_format_get_demangler(const GProgramFormat *);
@@ -108,60 +115,60 @@ GCompDemangler *g_binary_format_get_demangler(const GBinFormat *);
/* Protège ou lève la protection de l'accès aux symboles. */
-void g_binary_format_lock_unlock_symbols_rd(GBinFormat *, bool);
+void g_program_format_lock_unlock_symbols_rd(GProgramFormat *, bool);
-#define g_binary_format_lock_symbols_rd(f) g_binary_format_lock_unlock_symbols_rd(f, true)
-#define g_binary_format_unlock_symbols_rd(f) g_binary_format_lock_unlock_symbols_rd(f, false)
+#define g_program_format_lock_symbols_rd(f) g_program_format_lock_unlock_symbols_rd(f, true)
+#define g_program_format_unlock_symbols_rd(f) g_program_format_lock_unlock_symbols_rd(f, false)
/* Protège ou lève la protection de l'accès aux symboles. */
-void g_binary_format_lock_unlock_symbols_wr(GBinFormat *, bool);
+void g_program_format_lock_unlock_symbols_wr(GProgramFormat *, bool);
-#define g_binary_format_lock_symbols_wr(f) g_binary_format_lock_unlock_symbols_wr(f, true)
-#define g_binary_format_unlock_symbols_wr(f) g_binary_format_lock_unlock_symbols_wr(f, false)
+#define g_program_format_lock_symbols_wr(f) g_program_format_lock_unlock_symbols_wr(f, true)
+#define g_program_format_unlock_symbols_wr(f) g_program_format_lock_unlock_symbols_wr(f, false)
/* Assure qu'un verrou est bien posé pour l'accès aux symboles. */
#ifndef NDEBUG
-void g_binary_format_check_for_symbols_lock(const GBinFormat *);
+void g_program_format_check_for_symbols_lock(const GProgramFormat *);
#endif
/* Fournit la marque de dernière modification des symboles. */
-unsigned int g_binary_format_get_symbols_stamp(const GBinFormat *);
+unsigned int g_program_format_get_symbols_stamp(const GProgramFormat *);
/* Compte le nombre de symboles représentés. */
-size_t g_binary_format_count_symbols(const GBinFormat *);
+size_t g_program_format_count_symbols(const GProgramFormat *);
/* Fournit un symbole lié à un format. */
-GBinSymbol *g_binary_format_get_symbol(const GBinFormat *, size_t);
+GBinSymbol *g_program_format_get_symbol(const GProgramFormat *, size_t);
/* Ajoute un symbole à la collection du format binaire. */
-bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *);
+bool g_program_format_add_symbol(GProgramFormat *, GBinSymbol *);
/* Ajoute plusieurs symboles à la collection du format binaire. */
-bool g_binary_format_add_symbols(GBinFormat *, GBinSymbol **, size_t);
+bool g_program_format_add_symbols(GProgramFormat *, GBinSymbol **, size_t);
/* Retire un symbole de la collection du format binaire. */
-void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *);
+void g_program_format_remove_symbol(GProgramFormat *, GBinSymbol *);
/* Recherche le symbole correspondant à une étiquette. */
-bool g_binary_format_find_symbol_by_label(GBinFormat *, const char *, GBinSymbol **);
+bool g_program_format_find_symbol_by_label(GProgramFormat *, const char *, GBinSymbol **);
/* Recherche l'indice du symbole correspondant à une adresse. */
-bool g_binary_format_find_symbol_index_at(GBinFormat *, const vmpa2t *, size_t *);
+bool g_program_format_find_symbol_index_at(GProgramFormat *, const vmpa2t *, size_t *);
/* Recherche le symbole correspondant à une adresse. */
-bool g_binary_format_find_symbol_at(GBinFormat *, const vmpa2t *, GBinSymbol **);
+bool g_program_format_find_symbol_at(GProgramFormat *, const vmpa2t *, GBinSymbol **);
/* Recherche le symbole contenant une adresse. */
-bool g_binary_format_find_symbol_for(GBinFormat *, const vmpa2t *, GBinSymbol **);
+bool g_program_format_find_symbol_for(GProgramFormat *, const vmpa2t *, GBinSymbol **);
/* Recherche le symbole suivant celui lié à une adresse. */
-bool g_binary_format_find_next_symbol_at(GBinFormat *, const vmpa2t *, GBinSymbol **);
+bool g_program_format_find_next_symbol_at(GProgramFormat *, const vmpa2t *, GBinSymbol **);
/* Recherche le premier symbole inclus dans une zone mémoire. */
-bool g_binary_format_find_first_symbol_inside(GBinFormat *, const mrange_t *, size_t *);
+bool g_program_format_find_first_symbol_inside(GProgramFormat *, const mrange_t *, size_t *);
/* Recherche le symbole correspondant à une adresse. */
-bool g_binary_format_resolve_symbol(GBinFormat *, const vmpa2t *, bool, GBinSymbol **, phys_t *);
+bool g_program_format_resolve_symbol(GProgramFormat *, const vmpa2t *, bool, GBinSymbol **, phys_t *);
@@ -181,20 +188,21 @@ typedef enum _BinaryFormatError
/* Protège ou lève la protection de l'accès aux erreurs. */
-void g_binary_format_lock_unlock_errors(GBinFormat *, bool);
+void g_program_format_lock_unlock_errors(GProgramFormat *, bool);
-#define g_binary_format_lock_errors(f) g_binary_format_lock_unlock_errors(f, true)
-#define g_binary_format_unlock_errors(f) g_binary_format_lock_unlock_errors(f, false)
+#define g_program_format_lock_errors(f) g_program_format_lock_unlock_errors(f, true)
+#define g_program_format_unlock_errors(f) g_program_format_lock_unlock_errors(f, false)
/* Etend la liste des soucis détectés avec de nouvelles infos. */
-void g_binary_format_add_error(GBinFormat *, BinaryFormatError, const vmpa2t *, const char *);
+void g_program_format_add_error(GProgramFormat *, BinaryFormatError, const vmpa2t *, const char *);
/* Indique le nombre d'erreurs relevées au niveau assembleur. */
-size_t g_binary_format_count_errors(GBinFormat *);
+size_t g_program_format_count_errors(GProgramFormat *);
/* Fournit les éléments concernant un soucis détecté. */
-bool g_binary_format_get_error(GBinFormat *, size_t, BinaryFormatError *, vmpa2t *, char **);
+bool g_program_format_get_error(GProgramFormat *, size_t, BinaryFormatError *, vmpa2t *, char **);
+#endif
-#endif /* _FORMAT_FORMAT_H */
+#endif /* _FORMAT_PROGRAM_H */
diff --git a/src/framework.h b/src/framework.h
deleted file mode 100644
index e8e88fe..0000000
--- a/src/framework.h
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * framework.h - prototypes pour le fichier d'entrée du programme
- *
- * Copyright (C) 2024 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _FRAMEWORK_H
-#define _FRAMEWORK_H
-
-
-#include <glib-object.h>
-
-
-
-/* --------------------- DEFINITION D'APPLICATION PERSONNALISEE --------------------- */
-
-
-#define GTK_TYPE_CHRYSALIDE_FRAMEWORK gtk_chrysalide_framework_get_type()
-#define GTK_CHRYSALIDE_FRAMEWORK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CHRYSALIDE_FRAMEWORK, GtkChrysalideFramework))
-#define GTK_IS_CHRYSALIDE_FRAMEWORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CHRYSALIDE_FRAMEWORK))
-#define GTK_CHRYSALIDE_FRAMEWORK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CHRYSALIDE_FRAMEWORK, GtkChrysalideFrameworkClass))
-#define GTK_IS_CHRYSALIDE_FRAMEWORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CHRYSALIDE_FRAMEWORK))
-#define GTK_CHRYSALIDE_FRAMEWORK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CHRYSALIDE_FRAMEWORK, GtkChrysalideFrameworkClass))
-
-
-/* Définition de l'application principale graphique (instance) */
-typedef struct _GtkChrysalideFramework GtkChrysalideFramework;
-
-/* Définition de l'application principale graphique (classe) */
-typedef struct _GtkChrysalideFrameworkClass GtkChrysalideFrameworkClass;
-
-
-/* Indique le type défini pour une application principale graphique de Chrysalide. */
-GType gtk_chrysalide_framework_get_type(void);
-
-/* Crée une nouvelle application principale pour Chrysalide. */
-GtkChrysalideFramework *gtk_chrysalide_framework_new(void);
-
-
-
-/* ---------------------- POINT D'ENTREE PRINCIPAL D'EXECUTION ---------------------- */
-
-
-/* Point d'entrée du programme. */
-int main(int, char **);
-
-
-
-#endif /* _FRAMEWORK_H */
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index b5ea0f0..b0a7c31 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -1,50 +1,74 @@
BUILT_SOURCES = chrysamarshal.h chrysamarshal.c resources.h resources.c
-noinst_LTLIBRARIES = libglibext4.la libglibextui.la # libglibext.la
-
-libglibext_la_SOURCES = \
- comparison-int.h \
- comparison.h comparison.c \
- configuration-int.h \
- configuration.h configuration.c \
- gbinarycursor.h gbinarycursor.c \
- gbinportion-int.h \
- gbinportion.h gbinportion.c \
- glinecursor-int.h \
- glinecursor.h glinecursor.c \
- gnhash.h gnhash.c \
- notifier.h \
- objhole.h \
- proto.h \
- seq.h seq.c \
- _signal.h signal.c \
- singleton.h singleton.c \
- linetoken.h linetoken.c \
- umemslice-int.h \
- umemslice.h umemslice.c
-
-if BUILD_GTK_SUPPORT
-
-libglibext_la_SOURCES += \
- gloadedpanel-int.h \
- gloadedpanel.h gloadedpanel.c \
- named-int.h \
- named.h named.c
-
-endif
-
-libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+noinst_LTLIBRARIES = libglibext.la libglibextui.la
+
+# libglibext_la_SOURCES = \
+# configuration-int.h \
+# configuration.h configuration.c \
+# gbinarycursor.h gbinarycursor.c \
+# glinecursor-int.h \
+# glinecursor.h glinecursor.c \
+# gnhash.h gnhash.c \
+# notifier.h \
+# \
+# proto.h \
+# seq.h seq.c \
+# singleton.h singleton.c \
+# linetoken.h linetoken.c \
+# umemslice-int.h \
+# umemslice.h umemslice.c
+
+# if BUILD_GTK_SUPPORT
+
+# libglibext_la_SOURCES += \
+# gloadedpanel-int.h \
+# gloadedpanel.h gloadedpanel.c \
+# named-int.h \
+# named.h named.c
+
+# endif
+
+# libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
#libglibext_la_LIBADD = \
# generators/libglibextgenerators.la
-libglibext4_la_SOURCES = \
+libglibext_la_SOURCES = \
chrysamarshal.h chrysamarshal.c \
- helpers.h
-
-libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS)
+ comparable-int.h \
+ comparable.h comparable.c \
+ hashable-int.h \
+ hashable.h hashable.c \
+ helpers.h \
+ log-int.h \
+ log.h log.c \
+ objhole-int.h \
+ objhole.h objhole.c \
+ portion-int.h \
+ portion.h portion.c \
+ secstorage-int.h \
+ secstorage.h secstorage.c \
+ serialize-int.h \
+ serialize.h serialize.c \
+ sigredir.h sigredir.c \
+ singleton-int.h \
+ singleton.h singleton.c \
+ storage-int.h \
+ storage.h storage.c \
+ strbuilder-int.h \
+ strbuilder.h strbuilder.c \
+ tpmem-int.h \
+ tpmem.h tpmem.c \
+ work-int.h \
+ work.h work.c \
+ workgroup-int.h \
+ workgroup.h workgroup.c \
+ workqueue-int.h \
+ workqueue.h workqueue.c
+
+libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBZIP_CFLAGS)
RES_FILES = \
@@ -78,7 +102,7 @@ libglibextui_la_LIBADD = \
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
-dev_HEADERS = $(libglibext_la_SOURCES:%c=)
+dev_HEADERS = $(libglibext_la_SOURCES:%c=) $(libglibextui_la_SOURCES:%c=)
SUBDIRS = generators options
diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c
index 4862e9f..e3fb27b 100644
--- a/src/glibext/bufferline.c
+++ b/src/glibext/bufferline.c
@@ -24,14 +24,16 @@
#include "bufferline.h"
+#include <assert.h>
+#include <malloc.h>
+
+
#include "bufferline-int.h"
#if 0
-#include <assert.h>
-#include <malloc.h>
#include <string.h>
@@ -273,158 +275,12 @@ bool g_buffer_line_create(GBufferLine *line, size_t col_count)
}
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne à venir compléter. *
-* column = colonne de la ligne visée par l'insertion. *
-* tag = type de décorateur à utiliser. *
-* text = texte à insérer dans l'existant. *
-* length = taille du texte à traiter. *
-* style = gestionnaire de paramètres de rendu à consulter. *
-* creator = instance GLib quelconque à associer. *
-* *
-* Description : Ajoute du texte à formater dans une ligne donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator)
-{
- size_t index; /* Indice d'insertion */
- //content_origin *origin; /* Définition d'une origine */
-
- assert(column < line->col_count);
- assert(length > 0);
-
- index = append_text_to_line_column(&line->columns[column], tag, text, length, style);
-
- /*
- if (creator != NULL)
- {
- line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin));
-
- origin = &line->origins[line->ocount - 1];
-
- origin->coord.column = column;
- origin->coord.index = index;
-
- origin->creator = creator;
- g_object_ref(G_OBJECT(creator));
-
- }
- */
-
-}
-
-
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne de texte à manipuler. *
-* cr = contexte graphique dédié à la procédure. *
-* column = (première) colonne à traiter. *
-* y = ordonnée du point d'impression. *
-* style = style de rendu pour les bribes de texte. *
-* *
-* Description : Imprime la ligne de texte représentée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style)
-{
-#if 0
- GBufferLineClass *class; /* Stockage de briques de base */
- bool has_src_surface; /* Note une présence définie */
-#endif
- size_t max_column; /* Borne de fin des colonnes */
- int x; /* Point de départ d'impression*/
- size_t i; /* Boucle de parcours */
-
- /*
- if (line->flags != BLF_NONE)
- {
- class = G_BUFFER_LINE_GET_CLASS(line);
-
- if (line->flags & BLF_ENTRYPOINT)
- {
- cairo_set_source_surface(cairo, class->entrypoint_img, 5, y);
- has_src_surface = true;
- }
- else if (line->flags & BLF_BOOKMARK)
- {
- cairo_set_source_surface(cairo, class->bookmark_img, 5, y);
- has_src_surface = true;
- }
- else
- has_src_surface = false;
-
- if (has_src_surface)
- cairo_paint(cairo);
-
- }
- */
-
-
- /* Détermination de l'éventail des colonnes à traiter */
-
- if (column == line->merge_start)
- max_column = line->col_count;
-
- else if (column > line->merge_start)
- max_column = 0;
-
- else
- max_column = column + 1;
-
- /* Dessin du contenu de ces colonnes */
-
- x = 0;
-
- for (i = column; i < max_column; i++)
- draw_line_column(&line->columns[i], cr, &x, y, style);
-
-}
-
-
-
-
-
-
-
-
-
-
-#if 0
-
-
/******************************************************************************
* *
-* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
-* size = taille souhaitée de l'impression des positions. *
-* addr = localisation physique à venir représenter. *
+* Paramètres : line = ligne à venir compléter. *
+* column = indice de la colonne visée par l'insertion. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation physique à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -434,7 +290,7 @@ void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int
* *
******************************************************************************/
-void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr)
+void g_buffer_line_fill_physical(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr)
{
VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
@@ -448,20 +304,22 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size,
if (i == len)
i = len - 1;
+ assert(column < line->col_count);
+
if (i > 0)
- g_buffer_line_append_text(line, col, position, i, RTT_PHYS_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_PHYS_ADDR_PAD, position, i, NULL, NULL);
- g_buffer_line_append_text(line, col, &position[i], len - i, RTT_PHYS_ADDR, NULL);
+ g_buffer_line_append_text(line, column, TRT_PHYS_ADDR, &position[i], len - i, NULL, NULL);
}
/******************************************************************************
* *
-* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
-* size = taille souhaitée de l'impression des positions. *
-* addr = localisation virtuelle à venir représenter. *
+* Paramètres : line = ligne à venir compléter. *
+* column = indice de la colonne visée par l'insertion. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation virtuelle à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -471,7 +329,7 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size,
* *
******************************************************************************/
-void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr)
+void g_buffer_line_fill_virtual(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr)
{
VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
@@ -479,6 +337,8 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
vmpa2_virt_to_string(addr, size, position, &len);
+ assert(column < line->col_count);
+
if (has_virt_addr(addr))
{
for (i = 2; i < len; i++)
@@ -488,14 +348,14 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
i = len - 1;
if (i > 0)
- g_buffer_line_append_text(line, col, position, i, RTT_VIRT_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, i, NULL, NULL);
- g_buffer_line_append_text(line, col, &position[i], len - i, RTT_VIRT_ADDR, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR, &position[i], len - i, NULL, NULL);
}
else
- g_buffer_line_append_text(line, col, position, len, RTT_VIRT_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, len, NULL, NULL);
}
@@ -503,7 +363,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
/******************************************************************************
* *
* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
+* column = indice de la colonne visée par l'insertion. *
* content = contenu binaire global à venir lire. *
* range = localisation des données à venir lire et présenter.*
* max = taille maximale de la portion binaire en octets. *
@@ -516,7 +376,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
* *
******************************************************************************/
-void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent *content, const mrange_t *range, phys_t max)
+void g_buffer_line_fill_content(GBufferLine *line, size_t column, const GBinContent *content, const mrange_t *range, phys_t max)
{
phys_t length; /* Taille de la couverture */
bool truncated; /* Indique si le code est coupé*/
@@ -548,7 +408,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
if (required <= sizeof(static_buffer))
bin_code = static_buffer;
else
- bin_code = (char *)calloc(required, sizeof(char));
+ bin_code = calloc(required, sizeof(char));
/* Code brut */
@@ -589,7 +449,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
/* Conclusion */
- g_buffer_line_append_text(line, col, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
+ g_buffer_line_append_text(line, column, TRT_RAW_CODE, bin_code, iter - bin_code, NULL, NULL);
if (bin_code != static_buffer)
free(bin_code);
@@ -599,6 +459,146 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
/******************************************************************************
* *
+* Paramètres : line = ligne à venir compléter. *
+* column = colonne de la ligne visée par l'insertion. *
+* tag = type de décorateur à utiliser. *
+* text = texte à insérer dans l'existant. *
+* length = taille du texte à traiter. *
+* style = gestionnaire de paramètres de rendu à consulter. *
+* creator = instance GLib quelconque à associer. *
+* *
+* Description : Ajoute du texte à formater dans une ligne donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator)
+{
+ size_t index; /* Indice d'insertion */
+ //content_origin *origin; /* Définition d'une origine */
+
+ assert(column < line->col_count);
+ assert(length > 0);
+
+ index = append_text_to_line_column(&line->columns[column], tag, text, length, style);
+
+ /*
+ if (creator != NULL)
+ {
+ line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin));
+
+ origin = &line->origins[line->ocount - 1];
+
+ origin->coord.column = column;
+ origin->coord.index = index;
+
+ origin->creator = creator;
+ g_object_ref(G_OBJECT(creator));
+
+ }
+ */
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : line = ligne de texte à manipuler. *
+* cr = contexte graphique dédié à la procédure. *
+* column = (première) colonne à traiter. *
+* y = ordonnée du point d'impression. *
+* style = style de rendu pour les bribes de texte. *
+* *
+* Description : Imprime la ligne de texte représentée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style)
+{
+#if 0
+ GBufferLineClass *class; /* Stockage de briques de base */
+ bool has_src_surface; /* Note une présence définie */
+#endif
+ size_t max_column; /* Borne de fin des colonnes */
+ int x; /* Point de départ d'impression*/
+ size_t i; /* Boucle de parcours */
+
+ /*
+ if (line->flags != BLF_NONE)
+ {
+ class = G_BUFFER_LINE_GET_CLASS(line);
+
+ if (line->flags & BLF_ENTRYPOINT)
+ {
+ cairo_set_source_surface(cairo, class->entrypoint_img, 5, y);
+ has_src_surface = true;
+ }
+ else if (line->flags & BLF_BOOKMARK)
+ {
+ cairo_set_source_surface(cairo, class->bookmark_img, 5, y);
+ has_src_surface = true;
+ }
+ else
+ has_src_surface = false;
+
+ if (has_src_surface)
+ cairo_paint(cairo);
+
+ }
+ */
+
+
+ /* Détermination de l'éventail des colonnes à traiter */
+
+ if (column == line->merge_start)
+ max_column = line->col_count;
+
+ else if (column > line->merge_start)
+ max_column = 0;
+
+ else
+ max_column = column + 1;
+
+ /* Dessin du contenu de ces colonnes */
+
+ x = 0;
+
+ for (i = column; i < max_column; i++)
+ draw_line_column(&line->columns[i], cr, &x, y, style);
+
+}
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+
+
+/******************************************************************************
+* *
* Paramètres : line = ligne à venir consulter. *
* column = indice de la colonne visée par les recherches. *
* *
diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h
index d6a2e2d..e95ee2b 100644
--- a/src/glibext/bufferline.h
+++ b/src/glibext/bufferline.h
@@ -30,6 +30,8 @@
#include "helpers.h"
#include "tokenstyle.h"
+#include "../arch/vmpa.h"
+#include "../analysis/content.h"
@@ -45,8 +47,6 @@
#ifdef INCLUDE_GTK_SUPPORT
# include "widthtracker.h"
#endif
-#include "../analysis/content.h"
-#include "../arch/vmpa.h"
@@ -75,6 +75,9 @@ typedef struct _GBufferLineClass GBufferLineClass;
+
+
+
#define G_TYPE_BUFFER_LINE (g_buffer_line_get_type())
DECLARE_GTYPE(GBufferLine, g_buffer_line, G, BUFFER_LINE);
@@ -98,7 +101,14 @@ typedef enum _BufferLineFlags
/* Crée une nouvelle représentation de fragments de texte. */
GBufferLine *g_buffer_line_new(size_t);
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_physical(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_virtual(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
+/* Construit le tronc commun d'une ligne autour de son contenu. */
+void g_buffer_line_fill_content(GBufferLine *, size_t, const GBinContent *, const mrange_t *, phys_t);
/* Ajoute du texte à formater dans une ligne donnée. */
void g_buffer_line_append_text(GBufferLine *, size_t, TokenRenderingTag, const char *, size_t, const GTokenStyle *, GObject *);
diff --git a/src/glibext/comparable-int.h b/src/glibext/comparable-int.h
new file mode 100644
index 0000000..18972c2
--- /dev/null
+++ b/src/glibext/comparable-int.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparable-int.h - définitions internes propres aux opérations de comparaison d'objets
+ *
+ * Copyright (C) 2022-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_COMPARABLE_INT_H
+#define _GLIBEXT_COMPARABLE_INT_H
+
+
+#include "comparable.h"
+
+
+
+/* Réalise une comparaison étendue entre objets. */
+typedef int (* compare_object_fc) (const GComparableObject *, const GComparableObject *);
+
+
+/* Instance d'objet comparable (interface) */
+struct _GComparableObjectInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ compare_object_fc compare; /* Comparaison étendue */
+
+};
+
+
+
+#endif /* _GLIBEXT_COMPARABLE_INT_H */
diff --git a/src/glibext/comparable.c b/src/glibext/comparable.c
new file mode 100644
index 0000000..40fd110
--- /dev/null
+++ b/src/glibext/comparable.c
@@ -0,0 +1,124 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparable.c - opérations de comparaison d'objets
+ *
+ * Copyright (C) 2022-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "comparable.h"
+
+
+#include "comparable-int.h"
+#include "../common/sort.h"
+
+
+
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_comparable_object_default_init(GComparableObjectInterface *);
+
+
+
+/* Détermine le type d'une interface pour un objet comparable. */
+G_DEFINE_INTERFACE(GComparableObject, g_comparable_object, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_comparable_object_default_init(GComparableObjectInterface *iface)
+{
+ iface->compare = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* *
+* Description : Réalise une comparaison étendue entre objets. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_comparable_object_compare(const GComparableObject *object, const GComparableObject *other)
+{
+ int result; /* Bilan à retourner */
+ GType type_a; /* Type de l'object A */
+ GType type_b; /* Type de l'object B */
+ GComparableObjectInterface *iface; /* Interface utilisée */
+
+ type_a = G_OBJECT_TYPE(G_OBJECT(object));
+ type_b = G_OBJECT_TYPE(G_OBJECT(other));
+
+ assert(sizeof(GType) <= sizeof(unsigned long));
+
+ result = sort_unsigned_long(type_a, type_b);
+
+ if (result == 0)
+ {
+ iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->compare(object, other);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* *
+* Description : Détermine si deux objets sont fonctionnellement identiques. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gboolean g_comparable_object_is_equal(const GComparableObject *object, const GComparableObject *other)
+{
+ gboolean result; /* Bilan à renvoyer */
+ int ret; /* Bilan d'une comparaison */
+
+ ret = g_comparable_object_compare(object, other);
+
+ result = (ret == 0);
+
+ return result;
+
+}
diff --git a/src/glibext/comparable.h b/src/glibext/comparable.h
new file mode 100644
index 0000000..7a652ff
--- /dev/null
+++ b/src/glibext/comparable.h
@@ -0,0 +1,46 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparable.h - prototypes pour les opérations de comparaison d'objets
+ *
+ * Copyright (C) 2022-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_COMPARABLE_H
+#define _GLIBEXT_COMPARABLE_H
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_COMPARABLE_OBJECT (g_comparable_object_get_type())
+
+DECLARE_INTERFACE(GComparableObject, g_comparable_object, G, COMPARABLE_OBJECT);
+
+
+
+/* Réalise une comparaison étendue entre objets. */
+int g_comparable_object_compare(const GComparableObject *, const GComparableObject *);
+
+/* Détermine si deux objets sont fonctionnellement identiques. */
+gboolean g_comparable_object_is_equal(const GComparableObject *, const GComparableObject *);
+
+
+
+#endif /* _GLIBEXT_COMPARABLE_H */
diff --git a/src/glibext/comparison-int.h b/src/glibext/comparison-int.h
deleted file mode 100644
index 446f25d..0000000
--- a/src/glibext/comparison-int.h
+++ /dev/null
@@ -1,58 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * comparison-int.h - définitions internes propres aux opérations de comparaison d'objets
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_COMPARISON_INT_H
-#define _GLIBEXT_COMPARISON_INT_H
-
-
-#include "comparison.h"
-
-
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-typedef bool (* compare_rich_fc) (const GComparableItem *, const GComparableItem *, RichCmpOperation, bool *);
-
-
-/* Instance d'élément comparable (interface) */
-struct _GComparableItemIface
-{
- GTypeInterface base_iface; /* A laisser en premier */
-
- compare_rich_fc cmp_rich; /* Comparaison de façon précise*/
-
-};
-
-
-/* Redéfinition */
-typedef GComparableItemIface GComparableItemInterface;
-
-
-/* Réalise une comparaison riche entre valeurs entière. */
-bool compare_rich_integer_values_signed(long long, long long, RichCmpOperation);
-
-/* Réalise une comparaison riche entre valeurs entière. */
-bool compare_rich_integer_values_unsigned(unsigned long long, unsigned long long, RichCmpOperation);
-
-
-
-#endif /* _GLIBEXT_COMPARISON_INT_H */
diff --git a/src/glibext/comparison.c b/src/glibext/comparison.c
deleted file mode 100644
index 8ce6941..0000000
--- a/src/glibext/comparison.c
+++ /dev/null
@@ -1,199 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * comparison.c - opérations de comparaison d'objets
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "comparison.h"
-
-
-#include <assert.h>
-
-
-#include "comparison-int.h"
-
-
-
-/* Procède à l'initialisation de l'interface de comparaison. */
-static void g_comparable_item_default_init(GComparableItemInterface *);
-
-
-
-/* Détermine le type d'une interface pour un objet comparable. */
-G_DEFINE_INTERFACE(GComparableItem, g_comparable_item, G_TYPE_OBJECT)
-
-
-/******************************************************************************
-* *
-* Paramètres : iface = interface GLib à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'interface de comparaison. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_comparable_item_default_init(GComparableItemInterface *iface)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
-* other = second objet à consulter 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 : - *
-* *
-******************************************************************************/
-
-bool g_comparable_item_compare_rich(const GComparableItem *item, const GComparableItem *other, RichCmpOperation op, bool *status)
-{
- bool result; /* Etat à retourner */
- GComparableItemIface *iface; /* Interface utilisée */
-
- iface = G_COMPARABLE_ITEM_GET_IFACE(item);
-
- result = iface->cmp_rich(item, other, op, status);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier élément à consulter pour une comparaison. *
-* b = second objet à consulter pour une comparaison. *
-* op = opération de comparaison à réaliser. *
-* *
-* Description : Réalise une comparaison riche entre valeurs entière. *
-* *
-* Retour : Bilan des opérations de comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool compare_rich_integer_values_signed(long long a, long long b, RichCmpOperation op)
-{
- bool result; /* Bilan à retourner */
-
- switch (op)
- {
- case RCO_LT:
- result = (a < b);
- break;
-
- case RCO_LE:
- result = (a <= b);
- break;
-
- case RCO_EQ:
- result = (a == b);
- break;
-
- case RCO_NE:
- result = (a != b);
- break;
-
- case RCO_GT:
- result = (a > b);
- break;
-
- case RCO_GE:
- result = (a >= b);
- break;
-
- default:
- assert(false);
- result = false;
- break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier élément à consulter pour une comparaison. *
-* b = second objet à consulter pour une comparaison. *
-* op = opération de comparaison à réaliser. *
-* *
-* Description : Réalise une comparaison riche entre valeurs entière. *
-* *
-* Retour : Bilan des opérations de comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool compare_rich_integer_values_unsigned(unsigned long long a, unsigned long long b, RichCmpOperation op)
-{
- bool result; /* Bilan à retourner */
-
- switch (op)
- {
- case RCO_LT:
- result = (a < b);
- break;
-
- case RCO_LE:
- result = (a <= b);
- break;
-
- case RCO_EQ:
- result = (a == b);
- break;
-
- case RCO_NE:
- result = (a != b);
- break;
-
- case RCO_GT:
- result = (a > b);
- break;
-
- case RCO_GE:
- result = (a >= b);
- break;
-
- default:
- assert(false);
- result = false;
- break;
-
- }
-
- return result;
-
-}
diff --git a/src/glibext/comparison.h b/src/glibext/comparison.h
deleted file mode 100644
index 8d43210..0000000
--- a/src/glibext/comparison.h
+++ /dev/null
@@ -1,80 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * comparison.h - prototypes pour les opérations de comparaison d'objets
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _GLIBEXT_COMPARISON_H
-#define _GLIBEXT_COMPARISON_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-
-#define G_TYPE_COMPARABLE_ITEM (g_comparable_item_get_type())
-#define G_COMPARABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_COMPARABLE_ITEM, GComparableItem))
-#define G_COMPARABLE_ITEM_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_COMPARABLE_ITEM, GComparableItemIface))
-#define G_IS_COMPARABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_COMPARABLE_ITEM))
-#define G_IS_COMPARABLE_ITEM_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_COMPARABLE_ITEM))
-#define G_COMPARABLE_ITEM_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_COMPARABLE_ITEM, GComparableItemIface))
-
-
-/* Instance d'élément comparable (coquille vide) */
-typedef struct _GComparableItem GComparableItem;
-
-/* Instance d'élément comparable (interface) */
-typedef struct _GComparableItemIface GComparableItemIface;
-
-
-/* Modes de comparaison */
-typedef enum _RichCmpOperation
-{
- RCO_LT, /* Equivalent de '<' */
- RCO_LE, /* Equivalent de '<=' */
- RCO_EQ, /* Equivalent de '==' */
- RCO_NE, /* Equivalent de '!=' */
- RCO_GT, /* Equivalent de '>' */
- RCO_GE, /* Equivalent de '>°' */
-
-} RichCmpOperation;
-
-/* Détermination d'un besoin de comparaison supplémentaire */
-#define STATUS_NOT_EQUAL(_s, _o) \
- ({ \
- bool __result; \
- if (_o == RCO_LE || _o == RCO_EQ || _o == RCO_GE) \
- __result = !_s; \
- else \
- __result = _s; \
- __result; \
- })
-
-
-/* Détermine le type d'une interface pour un objet comparable. */
-GType g_comparable_item_get_type(void) G_GNUC_CONST;
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-bool g_comparable_item_compare_rich(const GComparableItem *, const GComparableItem *, RichCmpOperation, bool *);
-
-
-
-#endif /* _GLIBEXT_COMPARISON_H */
diff --git a/src/glibext/hashable-int.h b/src/glibext/hashable-int.h
new file mode 100644
index 0000000..f8a85e1
--- /dev/null
+++ b/src/glibext/hashable-int.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hashable-int.h - définitions internes propres aux calculs de l'empreinte d'un objet
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_HASHABLE_INT_H
+#define _GLIBEXT_HASHABLE_INT_H
+
+
+#include "hashable.h"
+
+
+
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+typedef guint (* hash_object_fc) (const GHashableObject *);
+
+
+/* Instance d'objet visant à être unique (interface) */
+struct _GHashableObjectInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ hash_object_fc hash; /* Réduction en valeur */
+
+};
+
+
+
+#endif /* _GLIBEXT_HASHABLE_INT_H */
diff --git a/src/glibext/hashable.c b/src/glibext/hashable.c
new file mode 100644
index 0000000..f988a90
--- /dev/null
+++ b/src/glibext/hashable.c
@@ -0,0 +1,82 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hashable.c - calculs de l'empreinte d'un objet
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "hashable.h"
+
+
+#include "hashable-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_hashable_object_default_init(GHashableObjectInterface *);
+
+
+
+/* Détermine le type d'une interface pour la réduction d'un objet à une valeur. */
+G_DEFINE_INTERFACE(GHashableObject, g_hashable_object, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de détermination. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hashable_object_default_init(GHashableObjectInterface *iface)
+{
+ iface->hash = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = objet dont l'instance est à consulter. *
+* *
+* Description : Calcule l'empreinte sur 32 bits d'un objet. *
+* *
+* Retour : Valeur de représentation, unique pour l'objet ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+guint g_hashable_object_hash(const GHashableObject *object)
+{
+ guint result; /* Valeur à retourner */
+ GHashableObjectInterface *iface; /* Interface utilisée */
+
+ iface = G_HASHABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->hash(object);
+
+ return result;
+
+}
diff --git a/src/glibext/hashable.h b/src/glibext/hashable.h
new file mode 100644
index 0000000..165c744
--- /dev/null
+++ b/src/glibext/hashable.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hashable.h - prototypes pour les calculs de l'empreinte d'un objet
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_HASHABLE_H
+#define _GLIBEXT_HASHABLE_H
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_HASHABLE_OBJECT (g_hashable_object_get_type())
+
+DECLARE_INTERFACE(GHashableObject, g_hashable_object, G, HASHABLE_OBJECT);
+
+
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+guint g_hashable_object_hash(const GHashableObject *);
+
+
+
+#endif /* _GLIBEXT_HASHABLE_H */
diff --git a/src/glibext/helpers.h b/src/glibext/helpers.h
index 04e51ad..6176245 100644
--- a/src/glibext/helpers.h
+++ b/src/glibext/helpers.h
@@ -29,6 +29,9 @@
#include <glib-object.h>
+#include "../common/compiler.h"
+
+
/**
* Les définitions issues de <glib-2.80>/gobject/gtype.h fournissent des macros
@@ -118,6 +121,31 @@
}
+/**
+ * Définition sous condition d'une inclusion d'interface. Cette inclusion se réalise
+ * lorsque la fonction d'initialisation renseignée est définie.
+ *
+ * Cette version étendue de la macro G_IMPLEMENT_INTERFACE d'origine est principalement
+ * pour les raffinements d'objets en forme graphique.
+ */
+
+#define G_IMPLEMENT_INTERFACE_IF_SYM(iface_tp_getter, iface_init) \
+ do \
+ { \
+ extern GType iface_tp_getter(void) __weak; \
+ extern void iface_init(GTypeInterface *, gpointer) __weak; \
+ if (&iface_tp_getter != NULL && &iface_init != NULL) \
+ { \
+ GType iface_type = iface_tp_getter(); \
+ const GInterfaceInfo implementation_info = { \
+ (GInterfaceInitFunc)(void (*)(void))iface_init, NULL, NULL \
+ }; \
+ g_type_add_interface_static(g_define_type_id, iface_type, &implementation_info);\
+ } \
+ } \
+ while (0);
+
+
/**
* Les principales fonctions incrémentant ou réduisant le nombre de références
@@ -193,4 +221,5 @@
#endif
+
#endif /* _GLIBEXT_HELPERS_H */
diff --git a/src/glibext/log-int.h b/src/glibext/log-int.h
new file mode 100644
index 0000000..3b3208a
--- /dev/null
+++ b/src/glibext/log-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log-int.h - prototypes internes pour la conservation à destination graphique des éléments de journalisation
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LOG_INT_H
+#define _GLIBEXT_LOG_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "log.h"
+
+
+
+/* Définition d'une conservation d'objets construits (instance) */
+struct _GLogEntry
+{
+ GObject parent; /* A laisser en premier */
+
+ LogMessageType type; /* Type de message porté */
+ char *msg; /* Contenu du message diffusé */
+
+};
+
+/* Définition d'une conservation d'objets construits (classe) */
+struct _GLogEntryClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une conservation pour élément de journalisation. */
+bool g_log_entry_create(GLogEntry *, LogMessageType, const char *);
+
+
+
+#endif /* _GLIBEXT_LOG_INT_H */
diff --git a/src/glibext/log.c b/src/glibext/log.c
new file mode 100644
index 0000000..039172c
--- /dev/null
+++ b/src/glibext/log.c
@@ -0,0 +1,306 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.c - conservation hors mémoire d'objets choisis
+ *
+ * Copyright (C) 2020-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "log.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "log-int.h"
+
+
+
+/* ---------------------------- ENTREE DE JOURNALISATION ---------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _LogEntryProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_ICON_NAME, /* Nom d'image de représentat° */
+ PROP_MESSAGE, /* Contenu du message diffusé */
+
+ N_PROPERTIES
+
+} LogEntryProperty;
+
+static GParamSpec *_log_entry_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des conservations d'objets en place. */
+static void g_log_entry_class_init(GLogEntryClass *);
+
+/* Initialise une instance de conservation d'objets en place. */
+static void g_log_entry_init(GLogEntry *);
+
+/* Supprime toutes les références externes. */
+static void g_log_entry_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_log_entry_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_log_entry_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ENTREE DE JOURNALISATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une conservation d'objets construits. */
+G_DEFINE_TYPE(GLogEntry, g_log_entry, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des conservations d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_class_init(GLogEntryClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_log_entry_dispose;
+ object->finalize = g_log_entry_finalize;
+ object->get_property = gtk_log_entry_get_property;
+
+ _log_entry_properties[PROP_ICON_NAME] =
+ g_param_spec_string("icon-name", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ _log_entry_properties[PROP_MESSAGE] =
+ g_param_spec_string("message", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _log_entry_properties);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = instance à initialiser. *
+* *
+* Description : Initialise une instance de conservation d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_init(GLogEntry *entry)
+{
+ entry->type = LMT_COUNT;
+ entry->msg = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_dispose(GObject *object)
+{
+ G_OBJECT_CLASS(g_log_entry_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_finalize(GObject *object)
+{
+ GLogEntry *entry; /* Version spécialisée */
+
+ entry = G_LOG_ENTRY(object);
+
+ if (entry->msg != NULL)
+ free(entry->msg);
+
+ G_OBJECT_CLASS(g_log_entry_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = espèce du message à représenter. *
+* msg = message à faire apparaître à l'écran. *
+* *
+* Description : Crée une conservation pour un élément de journalisation. *
+* *
+* Retour : Conservation mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GLogEntry *g_log_entry_new(LogMessageType type, const char *msg)
+{
+ GLogEntry *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_LOG_ENTRY, NULL);
+
+ if (!g_log_entry_create(result, type, msg))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = instance de conservation à initialiser pleinement. *
+* type = espèce du message à représenter. *
+* msg = message à faire apparaître à l'écran. *
+* *
+* Description : Met en place une conservation pour élément de journalisation.*
+* *
+* Retour : Conservation mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_log_entry_create(GLogEntry *entry, LogMessageType type, const char *msg)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ entry->type = type;
+ entry->msg = strdup(msg);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_log_entry_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GLogEntry *entry; /* Version spécialisée */
+
+ entry = G_LOG_ENTRY(object);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ switch (entry->type)
+ {
+ case LMT_INFO:
+ g_value_set_string(value, "dialog-information-symbolic");
+ break;
+
+ case LMT_PROCESS:
+ g_value_set_string(value, "system-run-symbolic");
+ break;
+
+ case LMT_WARNING:
+ case LMT_BAD_BINARY:
+ g_value_set_string(value, "dialog-warning-symbolic");
+ break;
+
+ case LMT_ERROR:
+ case LMT_EXT_ERROR:
+ g_value_set_string(value, "computer-fail-symbolic");
+ break;
+
+
+ case LMT_COUNT:
+ g_value_set_string(value, "dialog-question-symbolic");
+ break;
+
+ }
+ break;
+
+ case PROP_MESSAGE:
+ g_value_set_string(value, entry->msg);
+ break;
+
+ }
+
+}
diff --git a/src/glibext/log.h b/src/glibext/log.h
new file mode 100644
index 0000000..472773c
--- /dev/null
+++ b/src/glibext/log.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.h - prototypes pour la conservation à destination graphique des éléments de journalisation
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LOG_H
+#define _GLIBEXT_LOG_H
+
+
+#include "helpers.h"
+#include "../core/logs.h"
+
+
+
+#define G_TYPE_LOG_ENTRY (g_log_entry_get_type())
+
+DECLARE_GTYPE(GLogEntry, g_log_entry, G, LOG_ENTRY);
+
+
+/* Crée une conservation pour un élément de journalisation. */
+GLogEntry *g_log_entry_new(LogMessageType, const char *);
+
+
+
+#endif /* _GLIBEXT_LOG_H */
diff --git a/src/glibext/objhole-int.h b/src/glibext/objhole-int.h
new file mode 100644
index 0000000..dbfb412
--- /dev/null
+++ b/src/glibext/objhole-int.h
@@ -0,0 +1,169 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * objhole.h - définitions internes pour ll'utilisation d'un espace inutilisé dans la structure GObject
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_OBJHOLE_INT_H
+#define _GLIBEXT_OBJHOLE_INT_H
+
+
+#include "objhole.h"
+
+
+#include "../common/cpp.h"
+
+
+
+/**
+ * Une structure GObject a la définition suivante :
+ *
+ * struct _GObject
+ * {
+ * GTypeInstance g_type_instance;
+ * volatile guint ref_count;
+ * GData *qdata;
+ * };
+ *
+ * Chaque objet GLib alloué comporte ainsi 4 octets inutilisés :
+ *
+ * (gdb) pt /o GObject
+ * type = struct _GObject {
+ * / 0 | 8 / GTypeInstance g_type_instance;
+ * / 8 | 4 / guint ref_count;
+ * / XXX 4-byte hole /
+ * / 16 | 8 / GData *qdata;
+ *
+ * / total size (bytes): 24 /
+ * }
+ *
+ * La situation n'a pas échappé aux développeurs GLib, avec la définition réelle
+ * de la structure (cf. https://github.com/GNOME/glib/blob/main/gobject/gobject.c) :
+ *
+ * #if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8
+ * #define HAVE_OPTIONAL_FLAGS
+ * #endif
+ *
+ * typedef struct
+ * {
+ * GTypeInstance g_type_instance;
+ * guint ref_count;
+ * #ifdef HAVE_OPTIONAL_FLAGS
+ * guint optional_flags;
+ * #endif
+ * GData *qdata;
+ * } GObjectReal;
+ *
+ * G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal));
+ * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count));
+ * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata));
+ *
+ * L'espace entre les deux derniers champs ne peut donc être pleinement exploité deux fois.
+ */
+
+/**
+ * Les bits effectivements utilisés par GLib s'identifie ainsi (02/12/24) :
+ *
+ * $ wget -qO /dev/stdout https://raw.githubusercontent.com/GNOME/glib/refs/heads/main/gobject/gobject.c \
+ * | grep ' * #define OPTIONAL_FLAG_'
+ * #define OPTIONAL_FLAG_IN_CONSTRUCTION (1 << 0)
+ * #define OPTIONAL_FLAG_HAS_SIGNAL_HANDLER (1 << 1)
+ * #define OPTIONAL_FLAG_HAS_NOTIFY_HANDLER (1 << 2)
+ * #define OPTIONAL_FLAG_LOCK (1 << 3)
+ * #define OPTIONAL_FLAG_EVER_HAD_WEAK_REF (1 << 4)
+ *
+ * Les n premiers bits doivent ainsi être préservés, même s'il est possible de
+ * partager le bit de verrouilage OPTIONAL_FLAG_LOCK.
+ */
+
+
+#ifndef HAVE_OPTIONAL_FLAGS_IN_GOBJECT
+
+# if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P >= 8
+# define HAVE_OPTIONAL_FLAGS_IN_GOBJECT 1
+# else
+# define HAVE_OPTIONAL_FLAGS_IN_GOBJECT 0
+# endif
+
+#endif
+
+
+#define GOBJECT_LOCK_BIT 3
+
+
+/* Nouvelle version dense des objets (instance) */
+typedef struct _GThickObject
+{
+ /**
+ * (cf. structure GObjectReal officielle).
+ */
+
+ GTypeInstance g_type_instance; /* Type d'objet */
+ guint ref_count; /* Décompte des références */
+
+#ifdef HAVE_OPTIONAL_FLAGS_IN_GOBJECT
+ guint extra; /* Zone partagée avec GLib */
+#endif
+
+ GData *qdata; /* Données complémentaires ? */
+
+#ifndef HAVE_OPTIONAL_FLAGS_IN_GOBJECT
+ guint extra; /* Zone supplémentaire propre */
+#endif
+
+} GThickObject;
+
+/* Nouvelle version dense des objets (classe) */
+struct _GThickObjectClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/**
+ * Définition du périmètre et des moyens d'accès.
+ */
+
+/* GLib 2.83.0 - cfa36f5e9 */
+#define GOBJECT_RESERVED_EXTRA_BITS 5
+
+#define GET_GOBJECT_EXTRA(obj, tp) \
+ ({ \
+ BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
+ tp ___result; \
+ guint __val; \
+ __val = g_thick_object_get_extra(G_THICK_OBJECT(obj)); \
+ ___result = *(tp *)(guint []){ __val }; \
+ ___result; \
+ })
+
+#define SET_GOBJECT_EXTRA(obj, tp, data) \
+ ({ \
+ BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
+ BUILD_BUG_ON(sizeof(data) > sizeof(guint *)); \
+ guint __val; \
+ __val = *(guint *)data; \
+ g_thick_object_set_extra(G_THICK_OBJECT(obj), __val); \
+ })
+
+
+
+#endif /* _GLIBEXT_OBJHOLE_INT_H */
diff --git a/src/glibext/objhole.c b/src/glibext/objhole.c
new file mode 100644
index 0000000..fd6fbc9
--- /dev/null
+++ b/src/glibext/objhole.c
@@ -0,0 +1,256 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * objhole.c - utilisation d'un espace inutilisé dans la structure GObject
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "objhole.h"
+
+
+#include <assert.h>
+
+
+#include "objhole-int.h"
+
+
+
+/* Initialise la classe des objets à la structure dense. */
+static void g_thick_object_class_init(GThickObjectClass *);
+
+/* Initialise une instance d'objet à la structure dense. */
+static void g_thick_object_init(GThickObject *);
+
+/* Supprime toutes les références externes. */
+static void g_thick_object_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_thick_object_finalize(GObject *);
+
+
+
+G_DEFINE_TYPE(GThickObject, g_thick_object, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des objets à la structure dense. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_class_init(GThickObjectClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_thick_object_dispose;
+ object->finalize = g_thick_object_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance à initialiser. *
+* *
+* Description : Initialise une instance d'objet à la structure dense. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_init(GThickObject *obj)
+{
+ obj->extra = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_dispose(GObject *object)
+{
+ G_OBJECT_CLASS(g_thick_object_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(g_thick_object_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à manipuler. *
+* *
+* Description : Pose un verrou à l'aide du bit dédié de GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_thick_object_lock(GThickObject *obj)
+{
+ g_bit_lock((gint *)&obj->extra, GOBJECT_LOCK_BIT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à manipuler. *
+* *
+* Description : Retire un verrou via le bit dédié de GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_thick_object_unlock(GThickObject *obj)
+{
+ g_bit_unlock((gint *)&obj->extra, GOBJECT_LOCK_BIT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à manipuler. *
+* *
+* Description : Vérifie qu'un verrou est appliqué à l'aide du bit de GObject.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#ifndef NDEBUG
+bool g_thick_object_check_lock(GThickObject *obj)
+{
+ bool result; /* Bilan à retourner */
+ gboolean status; /* Bilan d'une tentative */
+
+ status = g_bit_trylock((gint *)&obj->extra, GOBJECT_LOCK_BIT);
+
+ result = (status == FALSE);
+
+ return result;
+
+}
+#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à consulter. *
+* *
+* Description : Fournit la valeur courante de la zone de stockage d'un objet.*
+* *
+* Retour : Valeur de 32 lues et expurgées des bits GLib. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+guint g_thick_object_get_extra(const GThickObject *obj)
+{
+ guint result; /* Valeur à retourner */
+ guint mask; /* Masque à appliquer */
+
+ result = g_atomic_int_get(&obj->extra);
+
+ assert(GOBJECT_RESERVED_EXTRA_BITS < 30);
+
+ mask = (1 << GOBJECT_RESERVED_EXTRA_BITS) - 1;
+
+ result &= ~mask;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à consulter. *
+* val = valeur de 32 à conserver. *
+* *
+* Description : Définit la valeur courante de la zone de stockage d'un objet.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_thick_object_set_extra(GThickObject *obj, guint val)
+{
+ guint mask; /* Masque à appliquer */
+
+ assert(GOBJECT_RESERVED_EXTRA_BITS < 30);
+
+ mask = (1 << GOBJECT_RESERVED_EXTRA_BITS) - 1;
+
+ assert((val & mask) == 0);
+
+ val &= ~mask;
+
+ g_atomic_int_and(&obj->extra, val | mask);
+
+ g_atomic_int_or(&obj->extra, val);
+
+}
diff --git a/src/glibext/objhole.h b/src/glibext/objhole.h
index 38f4bd5..461c37a 100644
--- a/src/glibext/objhole.h
+++ b/src/glibext/objhole.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* objhole.h - prototypes pour l'utilisation d'un espace inutilisé dans la structure GObject
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,118 +25,36 @@
#define _GLIBEXT_OBJHOLE_H
-#include <glib.h>
-#include <glib-object.h>
-
-
-#include "../common/cpp.h"
-
-
-
-/**
- * Une structure GObject a la définition suivante :
- *
- * struct _GObject
- * {
- * GTypeInstance g_type_instance;
- * volatile guint ref_count;
- * GData *qdata;
- * };
- *
- * En revanche, le fichier "glib/gobject/gobject.c" précise la définition
- * réelle de la structure selon l'environnement :
- *
- * #if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8
- * #define HAVE_OPTIONAL_FLAGS
- * #endif
- *
- * typedef struct
- * {
- * GTypeInstance g_type_instance;
- * guint ref_count;
- * #ifdef HAVE_OPTIONAL_FLAGS
- * guint optional_flags;
- * #endif
- * GData *qdata;
- * } GObjectReal;
- *
- * G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal));
- * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count));
- * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata));
- *
- * L'espace entre les deux derniers champs ne peut donc être pleinement exploité deux fois.
- */
-
-#if 0
-
-# define GET_GOBJECT_EXTRA(obj, tp) \
- ({ \
- BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
- tp *___result; \
- ___result = (tp *)(((guint *)&obj->ref_count) + 1); \
- BUILD_BUG_ON((___result + 1) == (tp *)&obj->qdata); \
- ___result; \
- })
-
+#ifndef NDEBUG
+# include <stdbool.h>
#endif
-/**
- * Choix du bit de verrou pour le champ "lock".
- *
- * Dans la structure exploitant le mot utilisé ici, ce verrou est généralement
- * placé dans le bit de poids fort pour les objets qui l'utilisent.
- */
+#include "../glibext/helpers.h"
+
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-# define HOLE_LOCK_BIT 31
+#define G_TYPE_THICK_OBJECT (g_thick_object_get_type())
-#elif __BYTE_ORDER == __BIG_ENDIAN
+DECLARE_GTYPE(GThickObject, g_thick_object, G, THICK_OBJECT);
-# define HOLE_LOCK_BIT 0
-#else
+/* Pose un verrou à l'aide du bit dédié de GObject. */
+void g_thick_object_lock(GThickObject *);
-# error "Unknown byte order"
+/* Retire un verrou via le bit dédié de GObject. */
+void g_thick_object_unlock(GThickObject *);
+/* Vérifie qu'un verrou est appliqué à l'aide du bit de GObject. */
+#ifndef NDEBUG
+bool g_thick_object_check_lock(GThickObject *obj);
#endif
+/* Fournit la valeur courante de la zone de stockage d'un objet. */
+guint g_thick_object_get_extra(const GThickObject *);
-/* Verrou d'accès pour une encapsulation */
-typedef struct _lockable_obj_extra_t
-{
- gint lock; /* Gestion d'accès aux fanions */
-
-} lockable_obj_extra_t;
-
-
-#define INIT_GOBJECT_EXTRA_LOCK(xtr) \
- do \
- { \
- lockable_obj_extra_t *__lockable; \
- __lockable = (lockable_obj_extra_t *)xtr; \
- __lockable->lock = 0; \
- } \
- while (0)
-
-#define LOCK_GOBJECT_EXTRA(xtr) \
- do \
- { \
- lockable_obj_extra_t *__lockable; \
- __lockable = (lockable_obj_extra_t *)xtr; \
- g_bit_lock(&__lockable->lock, HOLE_LOCK_BIT); \
- } \
- while (0)
-
-#define UNLOCK_GOBJECT_EXTRA(xtr) \
- do \
- { \
- lockable_obj_extra_t *__lockable; \
- __lockable = (lockable_obj_extra_t *)xtr; \
- g_bit_unlock(&__lockable->lock, HOLE_LOCK_BIT); \
- } \
- while (0)
+/* Définit la valeur courante de la zone de stockage d'un objet. */
+void g_thick_object_set_extra(GThickObject *, guint);
diff --git a/src/glibext/options/Makefile.am b/src/glibext/options/Makefile.am
index 448de7b..3f400c6 100644
--- a/src/glibext/options/Makefile.am
+++ b/src/glibext/options/Makefile.am
@@ -2,7 +2,8 @@
noinst_LTLIBRARIES = libglibextoptions.la
-libglibextoptions_la_SOURCES = \
+libglibextoptions_la_SOURCES = \
+ asm.h \
hex.h hex.c
libglibextoptions_la_CFLAGS = $(TOOLKIT_CFLAGS)
diff --git a/src/glibext/options/asm.h b/src/glibext/options/asm.h
new file mode 100644
index 0000000..d7a2c86
--- /dev/null
+++ b/src/glibext/options/asm.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * asm.h - prototypes pour les options de rendus de code désassemblé
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_OPTIONS_ASM_H
+#define _GLIBEXT_OPTIONS_ASM_H
+
+
+#include "../helpers.h"
+
+
+
+/* Liste des colonnes en options */
+typedef enum _DisassColumnOptions
+{
+ ACO_PHYSICAL, /* Position physique */
+ ACO_VIRTUAL, /* Adresse virtuelle */
+ ACO_BINARY, /* Contenu sous forme binaire */
+
+ ACO_COUNT
+
+} DisassColumnOptions;
+
+
+#define ACO_ASSEMBLY_LABEL (ACO_COUNT + 0) /* Etiquette dans les données */
+#define ACO_ASSEMBLY_HEAD (ACO_COUNT + 1) /* Instruction pour assembleur */
+#define ACO_ASSEMBLY (ACO_COUNT + 2) /* Code pour assembleur */
+#define ACO_COMMENTS (ACO_COUNT + 3) /* Commentaires éventuels */
+
+
+
+
+
+
+#if 0
+#define G_TYPE_HEX_OPTIONS (g_hex_options_get_type())
+
+DECLARE_GTYPE(GHexOptions, g_hex_options, G, HEX_OPTIONS);
+
+
+/* Crée un groupe d'options pour le rendu d'hexadécimal. */
+GHexOptions *g_hex_options_new(void);
+#endif
+
+
+#endif /* _GLIBEXT_OPTIONS_HEX_H */
diff --git a/src/glibext/gbinportion-int.h b/src/glibext/portion-int-ui.h
index a29f53c..a29f53c 100644
--- a/src/glibext/gbinportion-int.h
+++ b/src/glibext/portion-int-ui.h
diff --git a/src/glibext/portion-int.h b/src/glibext/portion-int.h
new file mode 100644
index 0000000..c044206
--- /dev/null
+++ b/src/glibext/portion-int.h
@@ -0,0 +1,69 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * portion-int.h - prototypes internes pour la définition interne des portions de binaire
+ *
+ * Copyright (C) 2019-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GLIBEXT_PORTION_INT_H
+#define GLIBEXT_PORTION_INT_H
+
+
+#include "portion.h"
+
+
+
+/* Portion de données binaires quelconques (instance) */
+struct _GBinaryPortion
+{
+ GObject parent; /* A laisser en premier */
+
+ char *desc; /* Désignation humaine */
+
+ mrange_t range; /* Emplacement dans le code */
+ bool continued; /* Suite d'une découpe ? */
+
+ PortionAccessRights rights; /* Droits d'accès */
+
+ GBinaryPortion **subs; /* Portions incluses */
+ size_t count; /* Quantité d'inclusions */
+
+};
+
+/* Portion de données binaires quelconques (classe) */
+struct _GBinaryPortionClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une description de partie de code vierge. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_create(GBinaryPortion *, const vmpa2t *, phys_t);
+
+
+
+#endif /* GLIBEXT_PORTION_INT_H */
diff --git a/src/glibext/gbinportion.c b/src/glibext/portion-ui.c
index 12e12fb..12e12fb 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/portion-ui.c
diff --git a/src/glibext/gbinportion.h b/src/glibext/portion-ui.h
index ea4b4aa..ea4b4aa 100644
--- a/src/glibext/gbinportion.h
+++ b/src/glibext/portion-ui.h
diff --git a/src/glibext/portion.c b/src/glibext/portion.c
new file mode 100644
index 0000000..096a39d
--- /dev/null
+++ b/src/glibext/portion.c
@@ -0,0 +1,974 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * portion.c - représentation graphique de portions de binaire
+ *
+ * Copyright (C) 2013-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "portion.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "portion-int.h"
+//#include "../analysis/human/asm/lang.h"
+#include "../common/extstr.h"
+#include "../common/sort.h"
+//#include "../core/columns.h"
+//#include "../glibext/gbinarycursor.h"
+//#include "../glibext/linegen-int.h"
+
+
+
+/* ------------------------------- PORTION DE BINAIRE ------------------------------- */
+
+
+/* Initialise la classe des portions de données binaires. */
+static void g_binary_portion_class_init(GBinaryPortionClass *);
+
+/* Initialise une instance de portion de données binaires. */
+static void g_binary_portion_init(GBinaryPortion *);
+
+/* Supprime toutes les références externes. */
+static void g_binary_portion_dispose(GBinaryPortion *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_binary_portion_finalize(GBinaryPortion *);
+
+
+
+/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */
+
+
+/* Détermine si une portion contient une adresse donnée. */
+static bool g_binary_portion_contains_vmpa(const GBinaryPortion *, const vmpa2t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PORTION DE BINAIRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour les portions de données binaires. */
+G_DEFINE_TYPE(GBinaryPortion, g_binary_portion, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des portions de données binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_class_init(GBinaryPortionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_portion_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_binary_portion_finalize;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = instance à initialiser. *
+* *
+* Description : Initialise une instance de portion de données binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_init(GBinaryPortion *portion)
+{
+ vmpa2t dummy; /* Coquille presque vide */
+
+ portion->desc = NULL;
+
+ init_vmpa(&dummy, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+ init_mrange(&portion->range, &dummy, VMPA_NO_VIRTUAL);
+
+ portion->continued = false;
+
+ portion->rights = PAC_NONE;
+
+ portion->subs = NULL;
+ portion->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_dispose(GBinaryPortion *portion)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < portion->count; i++)
+ g_clear_object(&portion->subs[i]);
+
+ G_OBJECT_CLASS(g_binary_portion_parent_class)->dispose(G_OBJECT(portion));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_portion_finalize(GBinaryPortion *portion)
+{
+ if (portion->desc != NULL)
+ free(portion->desc);
+
+ if (portion->subs != NULL)
+ free(portion->subs);
+
+ G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : addr = emplacement de la section à conserver. *
+* size = taille de la section à conserver. *
+* *
+* Description : Crée une description de partie de code vierge. *
+* *
+* Retour : Instance mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinaryPortion *g_binary_portion_new(const vmpa2t *addr, phys_t size)
+{
+ GBinaryPortion *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BINARY_PORTION, NULL);
+
+ if (!g_binary_portion_create(result, addr, size))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = instance à initialiser pleinement. *
+* addr = emplacement de la section à conserver. *
+* size = taille de la section à conserver. *
+* *
+* Description : Met en place une description de partie de code vierge. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_create(GBinaryPortion *portion, const vmpa2t *addr, phys_t size)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ init_mrange(&portion->range, addr, size);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premières informations à consulter. *
+* b = secondes informations à consulter. *
+* *
+* Description : Etablit la comparaison ascendante entre deux portions. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_binary_portion_compare(const GBinaryPortion **a, const GBinaryPortion **b)
+{
+ int result; /* Bilan à retourner */
+ const vmpa2t *addr_a; /* Adresse de la portion 'a' */
+ const vmpa2t *addr_b; /* Adresse de la portion 'b' */
+
+ addr_a = get_mrange_addr(&(*a)->range);
+ addr_b = get_mrange_addr(&(*b)->range);
+
+ result = cmp_vmpa(addr_a, addr_b);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à mettre à jour. *
+* desc = nom à donner à la partie. *
+* *
+* Description : Attribue une description humaine à une partie de code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_portion_set_desc(GBinaryPortion *portion, const char *desc)
+{
+ if (portion->desc != NULL)
+ free(portion->desc);
+
+ if (desc == NULL)
+ portion->desc = NULL;
+
+ else
+ {
+ portion->desc = strdup(desc);
+
+ if (portion->continued)
+ portion->desc = stradd(portion->desc, _(" (continued)"));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à consulter. *
+* *
+* Description : Fournit la description attribuée à une partie de code. *
+* *
+* Retour : Nom donné à la partie. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_binary_portion_get_desc(const GBinaryPortion *portion)
+{
+ return portion->desc;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à mettre à jour. *
+* *
+* Description : Fournit l'emplacement d'une partie de code binaire. *
+* *
+* Retour : Espace de couverture associé à la portion. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const mrange_t *g_binary_portion_get_range(const GBinaryPortion *portion)
+{
+ return &portion->range;
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à mettre à jour. *
+* max = taille maximale accordée à la portion. *
+* *
+* Description : Assure qu'une portion ne dépasse pas une position donnée. *
+* *
+* Retour : true si la portion a été modifiée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_limit_range(GBinaryPortion *portion, phys_t max)
+{
+ bool result; /* Bilan à retourner */
+ phys_t current; /* Taille courante */
+
+ current = get_mrange_length(&portion->range);
+
+ result = (current > max);
+
+ if (result)
+ set_mrange_length(&portion->range, max);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = portion dont la définition est à metre à jour. *
+* *
+* Description : Définit la nature de la portion en terme d'originalité. *
+* *
+* Retour : - *
+* *
+* Remarques : L'action ne modifie aucunement la description courante. *
+* C'est le changement de description qui s'appuie sur la *
+* notée ici. *
+* *
+******************************************************************************/
+
+void g_binary_portion_mark_as_continued(GBinaryPortion *portion, bool continued)
+{
+ portion->continued = continued;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = portion dont la définition est à consulter. *
+* *
+* Description : Indique la nature de la portion en terme d'originalité. *
+* *
+* Retour : true si la portion est la suite d'une portion découpée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_is_continuation(const GBinaryPortion *portion)
+{
+ return portion->continued;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à mettre à jour. *
+* rights = droits d'accès de la partie. *
+* *
+* Description : Définit les droits associés à une partie de code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_binary_portion_set_rights(GBinaryPortion *portion, PortionAccessRights rights)
+{
+ portion->rights = rights;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = description de partie à consulter. *
+* *
+* Description : Fournit les droits associés à une partie de code. *
+* *
+* Retour : Droits d'accès de la partie. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PortionAccessRights g_binary_portion_get_rights(const GBinaryPortion *portion)
+{
+ return portion->rights;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = portion principale à compléter. *
+* sub = portion à inclure dans la définition courante. *
+* *
+* Description : Procède à l'inclusion d'une portion dans une autre. *
+* *
+* Retour : Bilan de l'opération : true si inclusion, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_include(GBinaryPortion *portion, GBinaryPortion *sub)
+{
+ bool result; /* Bilan à retourner */
+ bool found; /* Zone d'accueil trouvée ? */
+ size_t best; /* Meilleur point d'insertion */
+ size_t missed; /* Indice de zone à déplacer */
+ const mrange_t *brange; /* Raccourci de confort d'usage*/
+ vmpa2t end; /* Fin de la zone commune */
+ phys_t overlapping; /* Taille de la zone commune */
+ bool continued; /* Suite d'une découpe ? */
+ GBinaryPortion *left_part; /* Partie intégrable */
+ vmpa2t start; /* Départ de la seconde partie */
+ GBinaryPortion *right_part; /* Partie restante */
+
+ int g_binary_portion_is_included(const GBinaryPortion **a, const GBinaryPortion **b)
+ {
+ int result; /* Bilan à retourner */
+
+ result = mrange_includes_mrange(&(*b)->range, &(*a)->range);
+
+ return result;
+
+ }
+
+ found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinaryPortion *),
+ (__compar_fn_t)g_binary_portion_is_included, &best);
+
+ if (!found)
+ {
+ /**
+ * On se prépare à réaliser une insertion au niveau courant. Mais des
+ * portions précédentes sont peut-être à déplacer dans la nouvelle zone :
+ *
+ * EXIDX 0x001178 0x00009178 0x00009178 0x00008 0x00008 R 0x4
+ * PHDR 0x000034 0x00008034 0x00008034 0x00120 0x00120 R E 0x4
+ * INTERP 0x000154 0x00008154 0x00008154 0x00019 0x00019 R 0x1
+ * LOAD 0x000000 0x00008000 0x00008000 0x01184 0x01184 R E 0x8000
+ *
+ * On refait donc une passe sur toutes les sous-portions du niveau.
+ *
+ * Cette approche a le mérite de traiter également et naturellement les
+ * sections définies dans le désordre :
+ *
+ * [21] .bss NOBITS 00088240 07823c 0018c8 00 WA 0 0 8
+ * [22] __libc_freeres_ptrs NOBITS 00089b08 07823c 000018 00 WA 0 0 4
+ * [23] .comment PROGBITS 00000000 07823c 000022 01 MS 0 0 1
+ *
+ * Quant aux cas de figure où les portions sont identiques, l'ordre d'appel
+ * induit l'ordre d'inclusion.
+ *
+ * Cela concerne par exemple les zones de données :
+ *
+ * En-têtes de section:
+ * [Nr] Nom Type Adr Décala.Taille ES Fan LN Inf Al
+ * ...
+ * [ 2] .data PROGBITS 00010098 000098 00000c 00 WA 0 0 1
+ *
+ * En-têtes de programme:
+ * Type Décalage Adr. vir. Adr.phys. T.Fich. T.Mém. Fan Alignement
+ * ...
+ * LOAD 0x000098 0x00010098 0x00010098 0x0000c 0x0000c RW 0x8000
+ *
+ */
+
+ int g_binary_portion_track_missed_inclusion(const GBinaryPortion **a, const GBinaryPortion **b)
+ {
+ int result; /* Bilan à retourner */
+
+ result = mrange_includes_mrange(&(*a)->range, &(*b)->range);
+
+ return result;
+
+ }
+
+ do
+ {
+ found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinaryPortion *),
+ (__compar_fn_t)g_binary_portion_track_missed_inclusion, &missed);
+
+ if (found)
+ {
+ result = g_binary_portion_include(sub, portion->subs[missed]);
+ assert(result);
+
+ portion->subs = _qdelete(portion->subs, &portion->count, sizeof(GBinaryPortion *), missed);
+
+ }
+
+ }
+ while (found);
+
+ /**
+ * Il peut arriver que certaines portions débordent de leur zone d'inclusion :
+ *
+ * [24] .bss NOBITS 00012088 002084 000044 00 WA 0 0 8
+ * [25] .ARM.attributes ARM_ATTRIBUTES 00000000 002084 000037 00 0 0 1
+ * [26] .shstrtab STRTAB 00000000 0020bb 0000ed 00 0 0 1
+ *
+ * Afin de respecter une certaine cohérence dans l'arbre des portions, on choisit
+ * de découper la portion qui déborde.
+ */
+
+ int g_binary_portion_track_partial_inclusion(const GBinaryPortion **a, const GBinaryPortion **b)
+ {
+ int result; /* Bilan à retourner */
+
+ result = cmp_mrange_with_vmpa(&(*b)->range, get_mrange_addr(&(*a)->range));
+
+ return result;
+
+ }
+
+ found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinaryPortion *),
+ (__compar_fn_t)g_binary_portion_track_partial_inclusion, &best);
+
+ if (found)
+ {
+ brange = &portion->subs[best]->range;
+
+ compute_mrange_end_addr(brange, &end);
+ overlapping = compute_vmpa_diff(get_mrange_addr(&sub->range), &end);
+
+ continued = g_binary_portion_is_continuation(sub);
+
+ /* Partie contenue */
+
+ left_part = g_binary_portion_new(get_mrange_addr(&sub->range), overlapping);
+
+ g_binary_portion_set_desc(left_part, sub->desc);
+ g_binary_portion_mark_as_continued(left_part, continued);
+ g_binary_portion_set_rights(left_part, sub->rights);
+
+ /* Partie qui déborde... */
+
+ /**
+ * Comme la portion incluante peut avoir une définition d'adresse
+ * virtuelle différente de celle de la portion incluse, on recalcule
+ * la position de départ de la seconde partie de la portion découpée
+ * à partir des données d'origine.
+ */
+
+ copy_vmpa(&start, get_mrange_addr(&sub->range));
+ advance_vmpa(&start, overlapping);
+
+ right_part = g_binary_portion_new(&start, get_mrange_length(&sub->range) - overlapping);
+
+ if (!continued)
+ g_binary_portion_mark_as_continued(right_part, true);
+
+ g_binary_portion_set_desc(right_part, sub->desc);
+
+ if (continued)
+ g_binary_portion_mark_as_continued(right_part, true);
+
+ g_binary_portion_set_rights(right_part, sub->rights);
+
+ /* Inclusions des parties */
+
+ result = g_binary_portion_include(portion, left_part);
+
+ if (result)
+ result = g_binary_portion_include(portion, right_part);
+
+ unref_object(left_part);
+ unref_object(right_part);
+
+ }
+
+ else
+ {
+ ref_object(sub);
+
+ portion->subs = qinsert(portion->subs, &portion->count, sizeof(GBinaryPortion *),
+ (__compar_fn_t)g_binary_portion_compare, &sub);
+
+ result = true;
+
+ }
+
+ }
+
+ /* Poursuite de l'inclusion dans la sous-portion adaptée... */
+ else
+ result = g_binary_portion_include(portion->subs[best], sub);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = première couche amorçant la visite. *
+* visitor = fonction à appeler à chaque étape de la descente. *
+* data = adresse pointant vers des données de l'utilisateur.*
+* *
+* Description : Parcourt un ensemble de portions binaires. *
+* *
+* Retour : true si la visite a été jusqu'à son terme, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_visit(GBinaryPortion *portion, visit_portion_fc visitor, void *data)
+{
+ bool result; /* Etat à retourner */
+
+ bool visit_portion(GBinaryPortion *p, GBinaryPortion *pp)
+ {
+ bool ret; /* Etat à retourner */
+ size_t i; /* Boucle de parcours */
+
+ if (p->count == 0)
+ ret = visitor(p, pp, BPV_SHOW, data);
+
+ else
+ {
+ ret = visitor(p, pp, BPV_ENTER, data);
+
+ for (i = 0; i < p->count && ret; i++)
+ ret = visit_portion(p->subs[i], p);
+
+ if (ret)
+ ret = visitor(p, pp, BPV_EXIT, data);
+
+ }
+
+ return ret;
+
+ }
+
+ result = visit_portion(portion, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PARCOURS D'ENSEMBLES DE PORTIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = portion mère à consulter. *
+* addr = adresse du point de recherche. *
+* *
+* Description : Détermine si une portion contient une adresse donnée. *
+* *
+* Retour : true ou false selon le résultat. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_binary_portion_contains_vmpa(const GBinaryPortion *portion, const vmpa2t *addr)
+{
+ bool result; /* Bilan à retourner */
+ const mrange_t *range; /* Emplacement de portion */
+
+ result = false;
+
+ range = g_binary_portion_get_range(portion);
+
+ /* Portion non allouée en mémoire : on écarte */
+ if (!has_virt_addr(get_mrange_addr(range)))
+ goto not_found;
+
+ result = mrange_contains_addr(range, addr);
+
+ not_found:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = couche de portions à parcourir pour les recherches.*
+* addr = adresse du point de recherche. *
+* *
+* Description : Recherche la portion présente à une adresse donnée. *
+* *
+* Retour : Portion trouvée à l'endroit indiqué. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinaryPortion *g_binary_portion_find_at_addr(GBinaryPortion *portion, const vmpa2t *addr)
+{
+ GBinaryPortion *result; /* Portion à retourner */
+ size_t i; /* Boucle de parcours */
+ GBinaryPortion *sub; /* Portion incluse à traiter */
+
+ result = NULL;
+
+ if (!g_binary_portion_contains_vmpa(portion, addr))
+ goto done;
+
+ for (i = 0; i < portion->count && result == NULL; i++)
+ {
+ sub = portion->subs[i];
+
+ if (!g_binary_portion_contains_vmpa(sub, addr))
+ continue;
+
+ result = g_binary_portion_find_at_addr(sub, addr);
+
+ }
+
+ if (result == NULL)
+ {
+ result = portion;
+ ref_object(result);
+ }
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = portion mère à consulter. *
+* off = position physique du point de recherche. *
+* *
+* Description : Détermine si une portion contient une position donnée. *
+* *
+* Retour : true ou false selon le résultat. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_binary_portion_contains_physical(const GBinaryPortion *portion, phys_t off)
+{
+ bool result; /* Bilan à retourner */
+ const mrange_t *range; /* Emplacement de portion */
+ const vmpa2t *addr; /* Départ de la portion */
+
+ range = g_binary_portion_get_range(portion);
+ addr = get_mrange_addr(range);
+
+ if (!has_phys_addr(addr))
+ result = false;
+
+ else
+ result = (addr->physical <= off && off < (addr->physical + range->length));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = couche de portions à parcourir pour les recherches.*
+* off = position physique à retrouver. *
+* pos = position correspondante. [OUT] *
+* *
+* Description : Fournit l'emplacement correspondant à une position physique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_translate_offset_into_vmpa(const GBinaryPortion *portion, phys_t off, vmpa2t *pos)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ GBinaryPortion *sub; /* Portion incluse à traiter */
+ const mrange_t *range; /* Emplacement de portion */
+ const vmpa2t *addr; /* Départ de la portion */
+
+ result = false;
+
+ for (i = 0; i < portion->count; i++)
+ {
+ sub = portion->subs[i];
+
+ if (!g_binary_portion_contains_physical(sub, off))
+ continue;
+
+ result = g_binary_portion_translate_offset_into_vmpa(sub, off, pos);
+
+ break;
+
+ }
+
+ if (i == portion->count)
+ {
+ result = g_binary_portion_contains_physical(portion, off);
+
+ if (result)
+ {
+ range = g_binary_portion_get_range(portion);
+ addr = get_mrange_addr(range);
+
+ if (has_virt_addr(get_mrange_addr(range)))
+ init_vmpa(pos, off, addr->virtual + off - addr->physical);
+
+ else
+ init_vmpa(pos, off, VMPA_NO_VIRTUAL);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = portion mère à consulter. *
+* virt = adresse virtuelle du point de recherche. *
+* *
+* Description : Détermine si une portion contient une adresse donnée. *
+* *
+* Retour : true ou false selon le résultat. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_binary_portion_contains_virtual(const GBinaryPortion *portion, virt_t virt)
+{
+ bool result; /* Bilan à retourner */
+ const mrange_t *range; /* Emplacement de portion */
+ const vmpa2t *addr; /* Départ de la portion */
+
+ range = g_binary_portion_get_range(portion);
+ addr = get_mrange_addr(range);
+
+ if (!has_virt_addr(addr))
+ result = false;
+
+ else
+ result = (addr->virtual <= virt && virt < (addr->virtual + range->length));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : portion = couche de portions à parcourir pour les recherches.*
+* virt = adresse virtuelle à retrouver. *
+* pos = position correspondante. [OUT] *
+* *
+* Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_portion_translate_address_into_vmpa(const GBinaryPortion *portion, virt_t virt, vmpa2t *pos)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ GBinaryPortion *sub; /* Portion incluse à traiter */
+ const mrange_t *range; /* Emplacement de portion */
+ const vmpa2t *addr; /* Départ de la portion */
+
+ result = false;
+
+ for (i = 0; i < portion->count; i++)
+ {
+ sub = portion->subs[i];
+
+ if (!g_binary_portion_contains_virtual(sub, virt))
+ continue;
+
+ result = g_binary_portion_translate_address_into_vmpa(sub, virt, pos);
+
+ break;
+
+ }
+
+ if (i == portion->count)
+ {
+ result = g_binary_portion_contains_virtual(portion, virt);
+
+ if (result)
+ {
+ range = g_binary_portion_get_range(portion);
+ addr = get_mrange_addr(range);
+
+ if (has_phys_addr(addr) && has_virt_addr(addr))
+ init_vmpa(pos, addr->physical + virt - addr->virtual, virt);
+
+ else
+ init_vmpa(pos, VMPA_NO_PHYSICAL, virt);
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/src/glibext/portion.h b/src/glibext/portion.h
new file mode 100644
index 0000000..88d69b6
--- /dev/null
+++ b/src/glibext/portion.h
@@ -0,0 +1,121 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * portion.h - prototypes pour la représentation graphique de portions de binaire
+ *
+ * Copyright (C) 2013-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_PORTION_H
+#define _GLIBEXT_PORTION_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+#include "../arch/vmpa.h"
+
+
+
+/* ------------------------------- PORTION DE BINAIRE ------------------------------- */
+
+
+#define G_TYPE_BINARY_PORTION (g_binary_portion_get_type())
+
+DECLARE_GTYPE(GBinaryPortion, g_binary_portion, G, BINARY_PORTION);
+
+
+/* Crée une description de partie de code vierge. */
+GBinaryPortion *g_binary_portion_new(const vmpa2t *, phys_t);
+
+/* Etablit la comparaison ascendante entre deux portions. */
+int g_binary_portion_compare(const GBinaryPortion **, const GBinaryPortion **);
+
+/* Attribue une description humaine à une partie de code. */
+void g_binary_portion_set_desc(GBinaryPortion *, const char *);
+
+/* Fournit la description attribuée à une partie de code. */
+const char *g_binary_portion_get_desc(const GBinaryPortion *);
+
+/* Fournit l'emplacement d'une partie de code binaire. */
+const mrange_t *g_binary_portion_get_range(const GBinaryPortion *);
+
+/* Assure qu'une portion ne dépasse pas une position donnée. */
+bool g_binary_portion_limit_range(GBinaryPortion *, phys_t);
+
+/* Définit la nature de la portion en terme d'originalité. */
+void g_binary_portion_mark_as_continued(GBinaryPortion *, bool);
+
+/* Indique la nature de la portion en terme d'originalité. */
+bool g_binary_portion_is_continuation(const GBinaryPortion *);
+
+/* Droits d'accès à une portion */
+typedef enum _PortionAccessRights
+{
+ PAC_NONE = (0 << 0), /* Aucun */
+ PAC_READ = (1 << 0), /* Lecture */
+ PAC_WRITE = (1 << 1), /* Ecriture */
+ PAC_EXEC = (1 << 2) /* Exécution */
+
+} PortionAccessRights;
+
+#define PAC_ALL ((PortionAccessRights)(PAC_READ | PAC_WRITE | PAC_EXEC))
+
+/* Définit les droits associés à une partie de code. */
+void g_binary_portion_set_rights(GBinaryPortion *, PortionAccessRights);
+
+/* Fournit les droits associés à une partie de code. */
+PortionAccessRights g_binary_portion_get_rights(const GBinaryPortion *);
+
+/* Procède à l'inclusion d'une portion dans une autre. */
+bool g_binary_portion_include(GBinaryPortion *, GBinaryPortion *);
+
+/* Sens des visites */
+typedef enum _BinaryPortionVisit
+{
+ BPV_ENTER, /* Arrivée sur une branche */
+ BPV_SHOW, /* Visite d'une feuille */
+ BPV_EXIT /* Départ d'une branche */
+
+} BinaryPortionVisit;
+
+
+/* Fonction appelée à chaque visite de portion.*/
+typedef bool (* visit_portion_fc) (GBinaryPortion *, GBinaryPortion *, BinaryPortionVisit, void *);
+
+/* Parcourt un ensemble de portions binaires. */
+bool g_binary_portion_visit(GBinaryPortion *, visit_portion_fc, void *);
+
+
+
+/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */
+
+
+/* Recherche la portion présente à une adresse donnée. */
+GBinaryPortion *g_binary_portion_find_at_addr(GBinaryPortion *, const vmpa2t *);
+
+/* Fournit l'emplacement correspondant à une position physique. */
+bool g_binary_portion_translate_offset_into_vmpa(const GBinaryPortion *, phys_t, vmpa2t *);
+
+/* Fournit l'emplacement correspondant à une adresse virtuelle. */
+bool g_binary_portion_translate_address_into_vmpa(const GBinaryPortion *, virt_t, vmpa2t *);
+
+
+
+#endif /* _GLIBEXT_BINPORTION_H */
diff --git a/src/glibext/secstorage-int.h b/src/glibext/secstorage-int.h
new file mode 100644
index 0000000..bbac133
--- /dev/null
+++ b/src/glibext/secstorage-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * secstorage-int.h - définitions internes pour la conservation sécurisée d'éléments de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_SECSTORAGE_INT_H
+#define _GLIBEXT_SECSTORAGE_INT_H
+
+
+#include "secstorage.h"
+
+
+
+/* Gardien des secrets avec support des stockages (instance) */
+struct _GSecretStorage
+{
+ GObject parent; /* A laisser en premier */
+
+ GSettings *settings; /* Configuration sollicitée */
+
+ void *master_key; /* Clef déverrouillée */
+
+};
+
+/* Gardien des secrets avec support des stockages (classe) */
+struct _GSecretStorageClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ /* Signaux */
+
+ void (* lock_update) (GSecretStorage *);
+
+};
+
+
+/* Met en place un gardien des secrets avec support de stockage. */
+bool g_secret_storage_create(GSecretStorage *, GSettings *);
+
+
+
+#endif /* _GLIBEXT_SECSTORAGE_INT_H */
diff --git a/src/glibext/secstorage.c b/src/glibext/secstorage.c
new file mode 100644
index 0000000..161214c
--- /dev/null
+++ b/src/glibext/secstorage.c
@@ -0,0 +1,950 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * secstorage.c - conservation sécurisée d'éléments de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "secstorage.h"
+
+
+#include <assert.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+
+#include "secstorage-int.h"
+#include "../core/logs.h"
+
+
+
+/**
+ * Les mécanismes de hachage de mot de passe doivent être utilisés avec un sel,
+ * et la longueur du sel doit être d’au moins 128 bits.
+ *
+ * Cette note concerne le hachage de mots de passe et non la dérivation de secrets
+ * cependant.
+ *
+ * Source : https://cyber.gouv.fr/sites/default/files/2021/03/anssi-guide-selection_crypto-1.0.pdf
+ */
+
+#define SECRET_STORAGE_SALT_SIZE (256 / 8)
+
+
+/**
+ * Nombre d'itérations pour PBKDF2 : en 2023, OWASP recommande 600000 itérations
+ * pour PBKDF2-HMAC-SHA256 (et 210000 pour PBKDF2-HMAC-SHA512).
+ *
+ * Source : https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
+ */
+
+#define PBKDF2_HMAC_SHA256_ITERATIONS (2 << 20)
+
+
+/**
+ * AES 256 : clef de 256 bits, IV de 128 bits
+ */
+
+#define SECRET_STORAGE_KEK_SIZE (256 / 8)
+
+#define SECRET_STORAGE_KEY_SIZE (256 / 8)
+
+#define SECRET_STORAGE_BLOCK_SIZE (128 / 8)
+
+#define SECRET_STORAGE_IV_SIZE SECRET_STORAGE_BLOCK_SIZE
+
+
+
+/* Initialise la classe des stockages de secrets. */
+static void g_secret_storage_class_init(GSecretStorageClass *);
+
+/* Initialise une instance de stockage de secrets. */
+static void g_secret_storage_init(GSecretStorage *);
+
+/* Supprime toutes les références externes. */
+static void g_secret_storage_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_secret_storage_finalize(GObject *);
+
+/* Teste un mot de passe par Déverrouillage de clef maître. */
+static bool g_secret_storage_check_primary_password(GSecretStorage *, const char *, void **);
+
+
+
+/* Indique le type défini pour un gardien des secrets avec support des stockages. */
+G_DEFINE_TYPE(GSecretStorage, g_secret_storage, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des stockages de secrets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_class_init(GSecretStorageClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_secret_storage_dispose;
+ object->finalize = g_secret_storage_finalize;
+
+ g_signal_new("lock-update",
+ G_TYPE_SECRET_STORAGE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GSecretStorageClass, lock_update),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = instance à initialiser. *
+* *
+* Description : Initialise une instance de stockage de secrets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_init(GSecretStorage *storage)
+{
+ storage->settings = NULL;
+
+ storage->master_key = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_dispose(GObject *object)
+{
+ GSecretStorage *storage; /* Version spécialisée */
+
+ storage = G_SECRET_STORAGE(object);
+
+ g_clear_object(&storage->settings);
+
+ G_OBJECT_CLASS(g_secret_storage_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_finalize(GObject *object)
+{
+ GSecretStorage *storage; /* Version spécialisée */
+
+ storage = G_SECRET_STORAGE(object);
+
+ if (storage->master_key != NULL)
+ free(storage->master_key);
+
+ G_OBJECT_CLASS(g_secret_storage_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : settings = éventuel espace de configuration à utiliser. *
+* *
+* Description : Créé un nouveau gardien des secrets avec support de stockage.*
+* *
+* Retour : Gestionnaire de stockage sécurisé mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSecretStorage *g_secret_storage_new(GSettings *settings)
+{
+ GSecretStorage *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_SECRET_STORAGE, NULL);
+
+ if (!g_secret_storage_create(result, settings))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = stockage sécurisé à initialiser. *
+* settings = éventuel espace de configuration à utiliser. *
+* *
+* Description : Met en place un gardien des secrets avec support de stockage.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_create(GSecretStorage *storage, GSettings *settings)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (settings != NULL)
+ {
+ ref_object(settings);
+ storage->settings = settings;
+ }
+ else
+ storage->settings = g_settings_new("re.chrysalide.framework.secstorage");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* *
+* Description : Détermine si une clef de chiffrement protégée est en place. *
+* *
+* Retour : Bilan de l'analyse. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_has_key(const GSecretStorage *storage)
+{
+ bool result; /* Bilan à retourner */
+ GVariant *value; /* Valeur de configuration */
+ gsize length; /* Taille d'une valeur donnée */
+
+ result = false;
+
+ value = g_settings_get_value(storage->settings, "master");
+
+ g_variant_get_fixed_array(value, &length, 1);
+
+ result = (length > SECRET_STORAGE_IV_SIZE);
+
+ g_variant_unref(value);
+
+ return result;;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* password = mot de passe principal à appliquer. *
+* *
+* Description : Définit un mot de passe pour protéger une clef maître. *
+* *
+* Retour : Bilan de la mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_set_password(GSecretStorage *storage, const char *passwd)
+{
+ bool result; /* Bilan à retourner */
+ unsigned char salt[SECRET_STORAGE_SALT_SIZE]; /* Sel pour la dérivation*/
+ int ret; /* Bilan à d'un appel */
+ GVariant *value; /* Valeur de configuration */
+ unsigned char kek[SECRET_STORAGE_KEK_SIZE]; /* Clef de protection */
+ unsigned char key[SECRET_STORAGE_KEY_SIZE]; /* Clef maître */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/
+ unsigned char encrypted[64]; /* Partie chiffrée à conserver */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (g_secret_storage_has_key(storage))
+ goto exit;
+
+ /* Création d'un sel pour la dérivation du mot de passe */
+
+ ret = RAND_bytes(salt, sizeof(salt));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /**
+ * La fonction g_variant_new_fixed_array() retourne un variant
+ * avec un décompte de référence flottant.
+ */
+
+ value = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ salt, SECRET_STORAGE_SALT_SIZE, sizeof(unsigned char));
+
+ /**
+ * Comme le variant à une référence flottante, la fonction
+ * g_settings_set_value() consomme cette référence.
+ *
+ * Il n'y a donc pas lieu d'appeler g_variant_unref().
+ */
+
+ g_settings_set_value(storage->settings, "salt", value);
+
+ /* Dérivation du mot de passe */
+
+ ret = PKCS5_PBKDF2_HMAC(passwd, strlen(passwd),
+ salt, SECRET_STORAGE_SALT_SIZE,
+ PBKDF2_HMAC_SHA256_ITERATIONS, EVP_sha256(),
+ SECRET_STORAGE_KEK_SIZE, kek);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /* Définition de la clef maître et de son IV de chiffrement */
+
+ ret = RAND_bytes(key, sizeof(key));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ ret = RAND_bytes(iv, sizeof(iv));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /* Chiffrement de la clef maître */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+
+ ret = EVP_EncryptInit_ex2(ctx, EVP_aes_256_wrap_pad(), kek, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ memcpy(encrypted, iv, SECRET_STORAGE_IV_SIZE);
+
+ iter = encrypted + SECRET_STORAGE_IV_SIZE;
+
+ ret = EVP_EncryptUpdate(ctx, iter, &outlen, key, SECRET_STORAGE_KEY_SIZE);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_EncryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ assert((iter - encrypted) < 64);
+
+ /* Conservation de la clef protégée */
+
+ value = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ encrypted, iter - encrypted, sizeof(unsigned char));
+
+ g_settings_set_value(storage->settings, "master", value);
+
+ g_signal_emit_by_name(storage, "lock-update");
+
+ result = true;
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* old = ancien mot de passe principal à vérifier. *
+* new = nouveau mot de passe principal à appliquer. *
+* *
+* Description : Modifie le mot de passe protégeant une clef maître. *
+* *
+* Retour : Bilan de la mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_change_password(GSecretStorage *storage, const char *old, const char *new)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if (!g_secret_storage_has_key(storage))
+ goto exit;
+
+ if (!g_secret_storage_check_primary_password(storage, old, NULL))
+ goto exit;
+
+ if (!g_secret_storage_is_locked(storage))
+ g_secret_storage_lock(storage);
+
+ g_settings_reset(storage->settings, "salt");
+ g_settings_reset(storage->settings, "master");
+
+ result = g_secret_storage_set_password(storage, new);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* password = mot de passe principal à appliquer. *
+* *
+* Description : Supprime le mot de passe protégeant une clef maître. *
+* *
+* Retour : Bilan de la mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_remove_password(GSecretStorage *storage, const char *passwd)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if (!g_secret_storage_has_key(storage))
+ goto exit;
+
+ if (!g_secret_storage_check_primary_password(storage, passwd, NULL))
+ goto exit;
+
+ if (!g_secret_storage_is_locked(storage))
+ g_secret_storage_lock(storage);
+
+ g_settings_reset(storage->settings, "salt");
+ g_settings_reset(storage->settings, "master");
+
+ g_signal_emit_by_name(storage, "lock-update");
+
+ result = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* *
+* Description : Détermine si la clef de chiffrement maître est vérouillée. *
+* *
+* Retour : Bilan de la détermination. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_is_locked(const GSecretStorage *storage)
+{
+ bool result; /* Bilan à retourner */
+
+ result = (storage->master_key == NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à manipuler. *
+* password = mot de passe principal à utiliser. *
+* master = éventuelle adresse pour un stockage de clef. [OUT]*
+* *
+* Description : Teste un mot de passe par Déverrouillage de clef maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_secret_storage_check_primary_password(GSecretStorage *storage, const char *passwd, void **master)
+{
+ bool result; /* Bilan à retourner */
+ GVariant *salt_value; /* Valeur du sel configuré */
+ gsize salt_length; /* Taille du sel conservé */
+ gconstpointer salt; /* Données associées #1 */
+ unsigned char kek[SECRET_STORAGE_KEK_SIZE]; /* Clef de protection */
+ int ret; /* Bilan à d'un appel */
+ GVariant *enc_value; /* Paramètres de chiffrement */
+ gsize enc_length; /* Taille de ces paramètrs */
+ gconstpointer encrypted; /* Données associées #2 */
+ EVP_CIPHER_CTX *ctx; /* Contexte de déchiffrement */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ unsigned char key[SECRET_STORAGE_KEY_SIZE]; /* Clef maître */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (!g_secret_storage_is_locked(storage))
+ {
+ result = true;
+ goto quick_exit;
+ }
+
+ /* Récupération du sel mis en place */
+
+ salt_value = g_settings_get_value(storage->settings, "salt");
+
+ salt = g_variant_get_fixed_array(salt_value, &salt_length, sizeof(bin_t));
+
+ if (salt_length != SECRET_STORAGE_SALT_SIZE)
+ goto exit_with_salt;
+
+ /* Dérivation du mot de passe */
+
+ ret = PKCS5_PBKDF2_HMAC(passwd, strlen(passwd),
+ salt, SECRET_STORAGE_SALT_SIZE,
+ PBKDF2_HMAC_SHA256_ITERATIONS, EVP_sha256(),
+ SECRET_STORAGE_KEK_SIZE, kek);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_salt;
+ }
+
+ /* Récupération des paramètres chiffrés */
+
+ enc_value = g_settings_get_value(storage->settings, "master");
+
+ encrypted = g_variant_get_fixed_array(enc_value, &enc_length, sizeof(bin_t));
+
+ if (enc_length <= SECRET_STORAGE_IV_SIZE)
+ goto exit_with_enc;
+
+ /* Déhiffrement de la clef maître */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_enc;
+ }
+
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+
+ memcpy(iv, encrypted, SECRET_STORAGE_IV_SIZE);
+
+ ret = EVP_DecryptInit_ex2(ctx, EVP_aes_256_wrap_pad(), kek, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter = key;
+
+ ret = EVP_DecryptUpdate(ctx, iter, &outlen,
+ ((unsigned char *)encrypted) + SECRET_STORAGE_IV_SIZE,
+ enc_length - SECRET_STORAGE_IV_SIZE);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_DecryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ assert((iter - key) == SECRET_STORAGE_KEY_SIZE);
+
+ /* Stockage de la clef maître en mémoire */
+
+ if (master != NULL)
+ {
+ *master = malloc(SECRET_STORAGE_KEY_SIZE);
+ memcpy(*master, key, SECRET_STORAGE_KEY_SIZE);
+ }
+
+ result = true;
+
+ /* Sortie */
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ exit_with_enc:
+
+ g_variant_unref(enc_value);
+
+ exit_with_salt:
+
+ g_variant_unref(salt_value);
+
+ quick_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à manipuler. *
+* password = mot de passe principal à utiliser. *
+* *
+* Description : Déverrouille la clef de chiffrement maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_unlock(GSecretStorage *storage, const char *passwd)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_secret_storage_check_primary_password(storage, passwd, &storage->master_key);
+
+ if (result)
+ g_signal_emit_by_name(storage, "lock-update");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à manipuler. *
+* *
+* Description : Verrouille la clef de chiffrement maître. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_secret_storage_lock(GSecretStorage *storage)
+{
+ if (storage->master_key != NULL)
+ {
+ free(storage->master_key);
+ storage->master_key = NULL;
+
+ g_signal_emit_by_name(storage, "lock-update");
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* in = séquence d'octets à traiter. *
+* out = séquence d'octets résultantes. [OUT] *
+* *
+* Description : Chiffre des données avec la clef de chiffrement maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_encrypt_data(const GSecretStorage *storage, const sized_binary_t *in, sized_binary_t *out)
+{
+ bool result; /* Bilan à retourner */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ int ret; /* Bilan à d'un appel */
+ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/
+ size_t needed; /* Taille de la sortie */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (g_secret_storage_is_locked(storage))
+ goto quick_exit;
+
+ /* Récupération de la clef maître et d'un IV de chiffrement */
+
+ ret = RAND_bytes(iv, sizeof(iv));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /* Préparation de la zone de réception */
+
+ needed = SECRET_STORAGE_IV_SIZE + ((in->size / SECRET_STORAGE_BLOCK_SIZE) + 1) * SECRET_STORAGE_BLOCK_SIZE;
+
+ setup_sized_binary(out, needed);
+
+ /* Chiffrement des données */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ ret = EVP_EncryptInit_ex2(ctx, EVP_aes_256_cbc(), storage->master_key, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ memcpy(out->data, iv, SECRET_STORAGE_IV_SIZE);
+
+ iter = out->bin_data + SECRET_STORAGE_IV_SIZE;
+
+ ret = EVP_EncryptUpdate(ctx, iter, &outlen, in->bin_data, in->size);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_EncryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ assert((iter - out->bin_data) == out->size);
+
+ result = true;
+
+ /* Sortie */
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ if (!result)
+ exit_sized_binary(out);
+
+ exit:
+ quick_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* in = séquence d'octets à traiter. *
+* out = séquence d'octets résultantes. [OUT] *
+* *
+* Description : Déchiffre des données avec la clef de chiffrement maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_decrypt_data(const GSecretStorage *storage, const sized_binary_t *in, sized_binary_t *out)
+{
+ bool result; /* Bilan à retourner */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ int ret; /* Bilan à d'un appel */
+ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/
+ size_t needed; /* Taille de la sortie */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (g_secret_storage_is_locked(storage))
+ goto quick_exit;
+
+ /* Récupération d'un IV de déchiffrement */
+
+ if (in->size < SECRET_STORAGE_IV_SIZE)
+ goto exit;
+
+ memcpy(iv, in->data, SECRET_STORAGE_IV_SIZE);
+
+ /* Préparation de la zone de réception */
+
+ needed = in->size - SECRET_STORAGE_IV_SIZE;
+
+ setup_sized_binary(out, needed);
+
+ /* Chiffrement des données */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ ret = EVP_DecryptInit_ex2(ctx, EVP_aes_256_cbc(), storage->master_key, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter = out->bin_data;
+
+ ret = EVP_DecryptUpdate(ctx, iter, &outlen,
+ in->bin_data + SECRET_STORAGE_IV_SIZE, in->size - SECRET_STORAGE_IV_SIZE);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_DecryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ assert((iter - out->bin_data) <= out->size);
+
+ resize_sized_binary(out, iter - out->bin_data);
+
+ result = true;
+
+ /* Sortie */
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ if (!result)
+ exit_sized_binary(out);
+
+ exit:
+ quick_exit:
+
+ return result;
+
+}
diff --git a/src/glibext/secstorage.h b/src/glibext/secstorage.h
new file mode 100644
index 0000000..ed3f79c
--- /dev/null
+++ b/src/glibext/secstorage.h
@@ -0,0 +1,74 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * secstorage.h - prototypes pour la conservation sécurisée d'éléments de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_SECSTORAGE_H
+#define _GLIBEXT_SECSTORAGE_H
+
+
+#include <stdbool.h>
+#include <gio/gio.h>
+
+
+#include "helpers.h"
+#include "../common/szbin.h"
+
+
+
+#define G_TYPE_SECRET_STORAGE (g_secret_storage_get_type())
+
+DECLARE_GTYPE(GSecretStorage, g_secret_storage, G, SECRET_STORAGE);
+
+
+/* Créé un nouveau gardien des secrets avec support de stockage. */
+GSecretStorage *g_secret_storage_new(GSettings *);
+
+/* Détermine si une clef de chiffrement protégée est en place. */
+bool g_secret_storage_has_key(const GSecretStorage *);
+
+/* Définit un mot de passe pour protéger une clef maître. */
+bool g_secret_storage_set_password(GSecretStorage *, const char *);
+
+/* Modifie le mot de passe protégeant une clef maître. */
+bool g_secret_storage_change_password(GSecretStorage *, const char *, const char *);
+
+/* Supprime le mot de passe protégeant une clef maître. */
+bool g_secret_storage_remove_password(GSecretStorage *, const char *);
+
+/* Détermine si la clef de chiffrement maître est vérouillée. */
+bool g_secret_storage_is_locked(const GSecretStorage *);
+
+/* Déverrouille la clef de chiffrement maître. */
+bool g_secret_storage_unlock(GSecretStorage *, const char *);
+
+/* Verrouille la clef de chiffrement maître. */
+void g_secret_storage_lock(GSecretStorage *);
+
+/* Chiffre des données avec la clef de chiffrement maître. */
+bool g_secret_storage_encrypt_data(const GSecretStorage *, const sized_binary_t *, sized_binary_t *);
+
+/* Déchiffre des données avec la clef de chiffrement maître. */
+bool g_secret_storage_decrypt_data(const GSecretStorage *, const sized_binary_t *, sized_binary_t *);
+
+
+
+#endif /* _GLIBEXT_SECSTORAGE_H */
diff --git a/src/analysis/storage/serialize-int.h b/src/glibext/serialize-int.h
index de8d3e3..df9c597 100644
--- a/src/analysis/storage/serialize-int.h
+++ b/src/glibext/serialize-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* serialize-int.h - définitions internes propres aux objets entreposables dans un cache
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,8 +21,8 @@
*/
-#ifndef _ANALYSIS_STORAGE_SERIALIZE_INT_H
-#define _ANALYSIS_STORAGE_SERIALIZE_INT_H
+#ifndef _GLIBEXT_SERIALIZE_INT_H
+#define _GLIBEXT_SERIALIZE_INT_H
#include "serialize.h"
@@ -33,14 +33,14 @@
/* Charge un objet depuis une mémoire tampon. */
-typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, packed_buffer_t *);
+typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, int);
/* Sauvegarde un objet dans une mémoire tampon. */
-typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, packed_buffer_t *);
+typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, int);
/* Intermédiaire pour la mise en cache d'objet (interface) */
-struct _GSerializableObjectIface
+struct _GSerializableObjectInterface
{
GTypeInterface base_iface; /* A laisser en premier */
@@ -50,9 +50,5 @@ struct _GSerializableObjectIface
};
-/* Redéfinition */
-typedef GSerializableObjectIface GSerializableObjectInterface;
-
-
-#endif /* _ANALYSIS_STORAGE_SERIALIZE_INT_H */
+#endif /* _GLIBEXT_SERIALIZE_INT_H */
diff --git a/src/analysis/storage/serialize.c b/src/glibext/serialize.c
index d1b0502..b43f0c2 100644
--- a/src/analysis/storage/serialize.c
+++ b/src/glibext/serialize.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* serialize.h - objets entreposables dans un cache
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -51,6 +51,8 @@ G_DEFINE_INTERFACE(GSerializableObject, g_serializable_object, G_TYPE_OBJECT)
static void g_serializable_object_default_init(GSerializableObjectInterface *iface)
{
+ iface->load = NULL;
+ iface->store = NULL;
}
@@ -58,10 +60,10 @@ static void g_serializable_object_default_init(GSerializableObjectInterface *ifa
/******************************************************************************
* *
* Paramètres : object = élément GLib à constuire. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à lire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
* *
-* Description : Charge un objet depuis une mémoire tampon. *
+* Description : Charge un objet depuis un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -69,14 +71,14 @@ static void g_serializable_object_default_init(GSerializableObjectInterface *ifa
* *
******************************************************************************/
-bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf)
+bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- GSerializableObjectIface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
- result = iface->load(object, storage, pbuf);
+ result = iface->load(object, storage, fd);
return result;
@@ -86,10 +88,10 @@ bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *sto
/******************************************************************************
* *
* Paramètres : object = élément GLib à consulter. *
-* storage = conservateur de données à manipuler ou NULL. *
-* pbuf = zone tampon à remplir. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Sauvegarde un objet dans une mémoire tampon. *
+* Description : Sauvegarde un objet dans un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -97,14 +99,14 @@ bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *sto
* *
******************************************************************************/
-bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf)
+bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
- GSerializableObjectIface *iface; /* Interface utilisée */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
- result = iface->store(object, storage, pbuf);
+ result = iface->store(object, storage, fd);
return result;
diff --git a/src/glibext/serialize.h b/src/glibext/serialize.h
new file mode 100644
index 0000000..c95ac30
--- /dev/null
+++ b/src/glibext/serialize.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * serialize.h - prototypes pour les objets entreposables dans un cache
+ *
+ * Copyright (C) 2020-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_SERIALIZE_H
+#define _GLIBEXT_SERIALIZE_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_SERIALIZABLE_OBJECT (g_serializable_object_get_type())
+
+DECLARE_INTERFACE(GSerializableObject, g_serializable_object, G, SERIALIZABLE_OBJECT);
+
+
+/* storage.h : définition d'une conservation d'objets construits */
+typedef struct _GObjectStorage GObjectStorage;
+
+
+/* Charge un objet depuis un flux de données. */
+bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, int);
+
+/* Sauvegarde un objet dans un flux de données. */
+bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, int);
+
+
+
+#endif /* _GLIBEXT_SERIALIZE_H */
diff --git a/src/glibext/signal.c b/src/glibext/sigredir.c
index 33290fb..67e8563 100644
--- a/src/glibext/signal.c
+++ b/src/glibext/sigredir.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * signal.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
+ * sigredir.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,49 +21,55 @@
*/
-#include "signal.h"
+#include "sigredir.h"
#include <assert.h>
#include <malloc.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <gobject/gclosure.h>
#include <gobject/gvaluecollector.h>
-/* Prototype pour le transfert d'exécution. */
-typedef void (* GSignalCallback) (gpointer, ...);
+/* Informations utiles à l'appel final */
+typedef struct _gsignal_wrapper_params_t
+{
+ GClosure *closure; /* Glue pour les appels */
+
+ guint n_params; /* Nombre de paramètres */
+ GValue instance_and_params[0]; /* Instance & paramètres */
+
+} gsignal_wrapper_params_t;
+
+/* Transmet un signal dans le contexte principal. */
+static gboolean to_main_wrapper(gpointer);
+/* Supprime de la mémoire le transporteur d'informations. */
+static void destroy_wrapper_params(gpointer);
/* Informations concernant une diffusion de signal */
-typedef struct _gsignal_wrapper_info
+typedef struct _gsignal_wrapper_info_t
{
gpointer instance; /* Instance GLib initiatrice */
+ gulong id; /* Identifiant de connexion */
GClosure *closure; /* Glue pour les appels */
- GType return_type; /* Type de la valeur retournée */
guint n_params; /* Nombre de paramètres */
- const GType *param_types; /* Type des paramètres associés*/
+ GType param_types[0]; /* Type des paramètres associés*/
- GValue return_value; /* Valeur de retour */
- GValue instance_and_params[0]; /* Instance & paramètres */
-
-} gsignal_wrapper_info;
-
-
-/* Transmet un signal dans le contexte principal. */
-static gboolean to_main_wrapper(gsignal_wrapper_info *);
+} gsignal_wrapper_info_t;
/* Réceptionne un signal et redirige son exécution. */
-static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *, ...);
/******************************************************************************
* *
-* Paramètres : info = collecteur d'informations sur la diffusion. *
+* Paramètres : data = collecteur d'informations sur la diffusion. *
* *
* Description : Transmet un signal dans le contexte principal. *
* *
@@ -73,11 +79,17 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
* *
******************************************************************************/
-static gboolean to_main_wrapper(gsignal_wrapper_info *info)
+static gboolean to_main_wrapper(gpointer data)
{
- g_closure_invoke(info->closure, NULL/*&info->return_value*/,
- info->n_params + 1, info->instance_and_params,
- NULL);
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_invoke(params->closure,
+ NULL /* return_value */,
+ params->n_params + 1,
+ params->instance_and_params,
+ NULL /* invocation_hint */);
return G_SOURCE_REMOVE;
@@ -86,6 +98,35 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
/******************************************************************************
* *
+* Paramètres : data = collecteur d'informations à supprimer. *
+* *
+* Description : Supprime de la mémoire le transporteur d'informations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void destroy_wrapper_params(gpointer data)
+{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+ guint i; /* Boucle de parcours */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_unref(params->closure);
+
+ for (i = 0; i < (params->n_params + 1); i++)
+ g_value_unset(params->instance_and_params + i);
+
+ free(params);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : info = collecteur d'informations sur la diffusion. *
* ... = arguments poussés par la GLib sur la pile. *
* *
@@ -97,23 +138,26 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
* *
******************************************************************************/
-static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *info, ...)
{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
GValue *param_values; /* Paramètres d'appel */
va_list ap; /* Liste d'arguments sur pile */
guint i; /* Boucle de parcours */
bool static_scope; /* Portée des arguments */
gchar *error; /* Eventuelle erreur inattendue*/
- //g_value_init(&info->return_value, info->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ params = calloc(1, sizeof(gsignal_wrapper_params_t) + sizeof(GValue) * (info->n_params + 1));
+
+ params->closure = info->closure;
+ g_closure_ref(info->closure);
- if (G_IS_VALUE(info->instance_and_params))
- g_value_unset(info->instance_and_params);
+ params->n_params = info->n_params;
- g_value_init(info->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
- g_value_set_instance(info->instance_and_params, info->instance);
+ g_value_init(params->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
+ g_value_set_instance(params->instance_and_params, info->instance);
- param_values = info->instance_and_params + 1;
+ param_values = params->instance_and_params + 1;
va_start(ap, info);
@@ -121,9 +165,6 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
for (i = 0; i < info->n_params; i++)
{
- if (G_IS_VALUE(param_values + i))
- g_value_unset(param_values + i);
-
static_scope = info->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
G_VALUE_COLLECT_INIT(param_values + i,
@@ -143,7 +184,28 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
va_end(ap);
if (error == NULL)
- g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, to_main_wrapper, params, destroy_wrapper_params);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = collecteur d'informations à supprimer. *
+* *
+* Description : Déconnecte un signal redirigé vers le contexte principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *info)
+{
+ g_signal_handler_disconnect(info->instance, info->id);
+
+ free(info);
}
@@ -165,41 +227,44 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
* *
******************************************************************************/
-gulong _g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
{
+ gsignal_wrapper_info_t *result; /* Structure à renvoyer */
guint signal_id; /* Identifiant du signal visé */
GSignalQuery query; /* Information sur le signal */
- gsignal_wrapper_info *info; /* Encapsulation des données */
/* Collection d'informations */
signal_id = g_signal_lookup(signal, G_TYPE_FROM_INSTANCE(instance));
g_signal_query(signal_id, &query);
+
assert(query.signal_id != 0);
+ assert(query.return_type == G_TYPE_NONE);
/* Allocation adaptée */
- info = calloc(1, sizeof(gsignal_wrapper_info) + sizeof(GValue) * (query.n_params + 1));
+ result = malloc(sizeof(gsignal_wrapper_info_t) + sizeof(GType) * query.n_params);
- info->instance = instance;
+ result->instance = instance;
if (flags & G_CONNECT_SWAPPED)
- info->closure = g_cclosure_new_swap(handler, data, NULL);
+ result->closure = g_cclosure_new_swap(handler, data, NULL);
else
- info->closure = g_cclosure_new(handler, data, NULL);
+ result->closure = g_cclosure_new(handler, data, NULL);
- g_closure_ref(info->closure);
- g_closure_sink(info->closure);
+ g_closure_ref(result->closure);
+ g_closure_sink(result->closure);
- g_closure_set_marshal(info->closure, marshal);
+ g_closure_set_marshal(result->closure, marshal);
- info->return_type = query.return_type;
- info->n_params = query.n_params;
- info->param_types = query.param_types;
+ result->n_params = query.n_params;
+ memcpy(result->param_types, query.param_types, sizeof(GType) * query.n_params);
- assert(query.return_type == G_TYPE_NONE);
+ /* Connexion au signal */
+
+ result->id = g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), result);
- return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info);
+ return result;
}
diff --git a/src/glibext/_signal.h b/src/glibext/sigredir.h
index 4f0ab4b..f394d77 100644
--- a/src/glibext/_signal.h
+++ b/src/glibext/sigredir.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * signal.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib
+ * sigredir.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,20 +21,23 @@
*/
-#ifndef _GLIBEXT_SIGNAL_H
-#define _GLIBEXT_SIGNAL_H
+#ifndef _GLIBEXT_SIGREDIR_H
+#define _GLIBEXT_SIGREDIR_H
#include <glib-object.h>
-#include <gobject/gclosure.h>
-#include <glib/gdataset.h>
-#include <glib/glist.h>
#include <gobject/gsignal.h>
+/* Informations concernant une diffusion de signal */
+typedef struct _gsignal_wrapper_info_t gsignal_wrapper_info_t;
+
/* Reproduit le comportement de la fonction g_signal_connect(). */
-gulong _g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal, GConnectFlags);
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal, GConnectFlags);
+
+/* Déconnecte un signal redirigé vers le contexte principal. */
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *);
#define g_signal_connect_to_main(instance, signal, handler, data, marshal) \
@@ -45,4 +48,4 @@ gulong _g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, G
-#endif /* _GLIBEXT_SIGNAL_H */
+#endif /* _GLIBEXT_SIGREDIR_H */
diff --git a/src/glibext/singleton-int.h b/src/glibext/singleton-int.h
index 3db17f9..747e64a 100644
--- a/src/glibext/singleton-int.h
+++ b/src/glibext/singleton-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* singleton-int.h - définitions internes propres aux réductions du nombre d'instances d'un même type
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,44 +29,61 @@
+/* ------------------ INTERFACE POUR CANDIDAT A UNE CENTRALISATION ------------------ */
+
+
/* Fournit une liste de candidats embarqués par un candidat. */
typedef GSingletonCandidate ** (* list_inner_instances_fc) (const GSingletonCandidate *, size_t *);
/* Met à jour une liste de candidats embarqués par un candidat. */
typedef void (* update_inner_instances_fc) (GSingletonCandidate *, GSingletonCandidate **, size_t);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-typedef guint (* hash_candidate_fc) (const GSingletonCandidate *);
-
-/* Détermine si deux candidats à l'unicité sont identiques. */
-typedef gboolean (* is_candidate_equal_fc) (const GSingletonCandidate *, const GSingletonCandidate *);
-
/* Marque un candidat comme figé. */
-typedef void (* set_candidate_ro_fc) (GSingletonCandidate *);
+typedef void (* mark_candidate_as_ro_fc) (GSingletonCandidate *);
/* Indique si le candidat est figé. */
typedef bool (* is_candidate_ro_fc) (const GSingletonCandidate *);
+/* Crée une copie modifiable d'un object unique. */
+typedef GSingletonCandidate * (* dup_candidate_fc) (const GSingletonCandidate *);
+
/* Instance d'objet visant à être unique (interface) */
-struct _GSingletonCandidateIface
+struct _GSingletonCandidateInterface
{
GTypeInterface base_iface; /* A laisser en premier */
list_inner_instances_fc list_inner; /* Récupération d'internes */
update_inner_instances_fc update_inner; /* Mise à jour des éléments */
- hash_candidate_fc hash; /* Prise d'empreinte */
- is_candidate_equal_fc is_equal; /* Comparaison */
-
- set_candidate_ro_fc set_ro; /* Bascule en mode figé */
+ mark_candidate_as_ro_fc mark_as_ro; /* Bascule en mode figé */
is_candidate_ro_fc is_ro; /* Consultation de l'état */
+ dup_candidate_fc dup; /* Création de copie modifiable*/
+
+};
+
+
+
+/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
+
+
+/* Définition d'un compacteur d'instances de types (instance) */
+struct _GSingletonFactory
+{
+ GObject parent; /* A laisser en premier */
+
+ GHashTable *table; /* Suivi des conservations */
+ GMutex access; /* Verrou pour la concurrence */
+
};
+/* Définition d'un compacteur d'instances de types (classe) */
+struct _GSingletonFactoryClass
+{
+ GObjectClass parent; /* A laisser en premier */
-/* Redéfinition */
-typedef GSingletonCandidateIface GSingletonCandidateInterface;
+};
diff --git a/src/glibext/singleton.c b/src/glibext/singleton.c
index 78a3ad4..ed49934 100644
--- a/src/glibext/singleton.c
+++ b/src/glibext/singleton.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* singleton.c - réduction du nombre d'instances d'un même type
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,52 +25,35 @@
#include <assert.h>
+#include <malloc.h>
+#include "comparable.h"
+#include "hashable.h"
#include "singleton-int.h"
/* ------------------ INTERFACE POUR CANDIDAT A UNE CENTRALISATION ------------------ */
+
/* Procède à l'initialisation de l'interface de rassemblement. */
static void g_singleton_candidate_default_init(GSingletonCandidateInterface *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *, size_t *);
+
/* Met à jour une liste de candidats embarqués par un candidat. */
static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *, GSingletonCandidate **, size_t);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint _g_singleton_candidate_hash(GSingletonCandidate *, GList **);
-
-/* Détermine si deux candidats à l'unicité sont identiques. */
-static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *, GSingletonCandidate *, GList **);
-
/* Marque un candidat comme figé. */
-static void _g_singleton_candidate_set_read_only(GSingletonCandidate *, GList **);
+static void g_singleton_candidate_mark_as_read_only(GSingletonCandidate *);
/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
-/* Définition d'un compacteur d'instances de types (instance) */
-struct _GSingletonFactory
-{
- GObject parent; /* A laisser en premier */
-
- GHashTable *table; /* Suivi des conservations */
- GMutex access; /* Verrou pour la concurrence */
-
-};
-
-/* Définition d'un compacteur d'instances de types (classe) */
-struct _GSingletonFactoryClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
/* Initialise la classe des compacteurs d'instances de types. */
static void g_singleton_factory_class_init(GSingletonFactoryClass *);
@@ -90,8 +73,10 @@ static void g_singleton_factory_finalize(GSingletonFactory *);
/* ---------------------------------------------------------------------------------- */
-/* Détermine le type d'une interface pour la lecture de binaire. */
-G_DEFINE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT)
+/* Détermine le type d'une interface pour la constitution d'objets uniques. */
+G_DEFINE_INTERFACE_WITH_CODE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT,;
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_COMPARABLE_OBJECT);
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_HASHABLE_OBJECT))
/******************************************************************************
@@ -108,6 +93,13 @@ G_DEFINE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT)
static void g_singleton_candidate_default_init(GSingletonCandidateInterface *iface)
{
+ iface->list_inner = NULL;
+ iface->update_inner = NULL;
+
+ iface->mark_as_ro = NULL;
+ iface->is_ro = NULL;
+
+ iface->dup = NULL;
}
@@ -128,14 +120,17 @@ static void g_singleton_candidate_default_init(GSingletonCandidateInterface *ifa
GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *candidate, size_t *count)
{
GSingletonCandidate **result; /* Instances à retourner */
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
if (iface->list_inner == NULL)
{
+ assert(iface->update_inner == NULL);
+
*count = 0;
result = NULL;
+
}
else
@@ -162,7 +157,7 @@ GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingleto
static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *candidate, GSingletonCandidate **instances, size_t count)
{
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
@@ -181,82 +176,36 @@ static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *ca
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* Description : Marque un candidat comme figé. *
* *
-* Retour : Empreinte de l'élément représenté. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static guint _g_singleton_candidate_hash(GSingletonCandidate *candidate, GList **processed)
+static void g_singleton_candidate_mark_as_read_only(GSingletonCandidate *candidate)
{
- guint result; /* Valeur à retourner */
- GList *skip; /* Détection de boucle */
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
GSingletonCandidate **children; /* Instances internes */
size_t count; /* Quantité de ces instances */
size_t i; /* Boucle de parcours */
- skip = g_list_find(*processed, candidate);
-
- if (skip != NULL)
- result = 0;
-
- else
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
-
- result = iface->hash(candidate);
-
- *processed = g_list_append(*processed, candidate);
-
- children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- for (i = 0; i < count; i++)
- {
- result ^= _g_singleton_candidate_hash(children[i], processed);
- g_object_unref(G_OBJECT(children[i]));
- }
+ iface->mark_as_ro(candidate);
- if (children != NULL)
- free(children);
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ for (i = 0; i < count; i++)
+ {
+ g_singleton_candidate_mark_as_read_only(children[i]);
+ unref_object(G_OBJECT(children[i]));
}
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
-* *
-* Retour : Empreinte de l'élément représenté. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-guint g_singleton_candidate_hash(GSingletonCandidate *candidate)
-{
- guint result; /* Valeur à retourner */
- GList *processed; /* Suivi des traitements */
-
- processed = NULL;
-
- result = _g_singleton_candidate_hash(candidate, &processed);
-
- assert(processed != NULL);
-
- g_list_free(processed);
-
- return result;
+ if (children != NULL)
+ free(children);
}
@@ -264,116 +213,43 @@ guint g_singleton_candidate_hash(GSingletonCandidate *candidate)
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
+* Description : Indique si le candidat est figé. *
* *
-* Retour : Bilan de la comparaison. *
+* Retour : true si le contenu du candidat ne peut plus être modifié. *
* *
* Remarques : - *
* *
******************************************************************************/
-static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSingletonCandidate *other, GList **processed)
+bool g_singleton_candidate_is_read_only(const GSingletonCandidate *candidate)
{
- gboolean result; /* Bilan à renvoyer */
- GList *skip; /* Détection de boucle */
- GSingletonCandidateIface *iface; /* Interface utilisée */
- GSingletonCandidate **children[2]; /* Instances internes */
- size_t count[2]; /* Quantité de ces instances */
+ bool result; /* Etat à retourner */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
+#ifndef NDEBUG
+ GSingletonCandidate **children; /* Instances internes */
+ size_t count; /* Quantité de ces instances */
size_t i; /* Boucle de parcours */
+#endif
- skip = g_list_find(processed[0], candidate);
-
- if (skip != NULL)
- result = (g_list_find(processed[1], other) != NULL);
-
- else
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
-
- result = iface->is_equal(candidate, other);
-
- processed[0] = g_list_append(processed[0], candidate);
- processed[1] = g_list_append(processed[1], other);
-
- if (!result)
- goto done;
-
- children[0] = g_singleton_candidate_list_inner_instances(candidate, &count[0]);
- children[1] = g_singleton_candidate_list_inner_instances(other, &count[1]);
-
- if (count[0] != count[1])
- {
- for (i = 0; i < count[0]; i++)
- g_object_unref(G_OBJECT(children[0][i]));
-
- for (i = 0; i < count[1]; i++)
- g_object_unref(G_OBJECT(children[1][i]));
-
- }
-
- else
- {
- for (i = 0; i < count[0] && result; i++)
- {
- result = _g_singleton_candidate_is_equal(children[0][i], children[1][i], processed);
- g_object_unref(G_OBJECT(children[0][i]));
- g_object_unref(G_OBJECT(children[1][i]));
- }
-
- for (; i < count[0]; i++)
- {
- g_object_unref(G_OBJECT(children[0][i]));
- g_object_unref(G_OBJECT(children[1][i]));
- }
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- if (children[0] != NULL)
- free(children[0]);
+ result = iface->is_ro(candidate);
- if (children[1] != NULL)
- free(children[1]);
+#ifndef NDEBUG
- }
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ for (i = 0; i < count; i++)
+ {
+ assert(result == g_singleton_candidate_is_read_only(children[i]));
+ unref_object(G_OBJECT(children[i]));
}
- done:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
-* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gboolean g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSingletonCandidate *other)
-{
- gboolean result; /* Bilan à renvoyer */
- GList *processed[2]; /* Suivi des traitements */
+ if (children != NULL)
+ free(children);
- processed[0] = NULL;
- processed[1] = NULL;
-
- result = _g_singleton_candidate_is_equal(candidate, other, processed);
-
- assert(processed[0] != NULL);
- assert(processed[1] != NULL);
-
- g_list_free(processed[0]);
- g_list_free(processed[1]);
+#endif
return result;
@@ -383,97 +259,60 @@ gboolean g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSinglet
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Marque un candidat comme figé. *
+* Description : Crée une copie modifiable d'un object unique. *
* *
-* Retour : - *
+* Retour : Nouvelle instance mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void _g_singleton_candidate_set_read_only(GSingletonCandidate *candidate, GList **processed)
+GSingletonCandidate *g_singleton_candidate_dup(const GSingletonCandidate *candidate)
{
- GList *skip; /* Détection de boucle */
- GSingletonCandidateIface *iface; /* Interface utilisée */
- GSingletonCandidate **children; /* Instances internes */
- size_t count; /* Quantité de ces instances */
+ GSingletonCandidate *result; /* Instance à retourner */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
+ size_t count; /* Quantité d'objets internes */
+ GSingletonCandidate **children; /* Liste d'instances internes */
size_t i; /* Boucle de parcours */
+ GSingletonCandidate **new_children; /* Nouvelle liste d'instances */
- skip = g_list_find(*processed, candidate);
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- if (skip == NULL)
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
+ result = iface->dup(candidate);
- iface->set_ro(candidate);
+ assert(!g_singleton_candidate_is_read_only(result));
- *processed = g_list_append(*processed, candidate);
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
- children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ if (count > 0)
+ {
+ new_children = malloc(count * sizeof(GSingletonCandidate *));
for (i = 0; i < count; i++)
{
- _g_singleton_candidate_set_read_only(candidate, processed);
- g_object_unref(G_OBJECT(children[i]));
- }
-
- if (children != NULL)
- free(children);
-
- }
-
-}
+ new_children[i] = g_singleton_candidate_dup(children[i]);
+ assert(!g_singleton_candidate_is_read_only(new_children[i]));
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* *
-* Description : Marque un candidat comme figé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_singleton_candidate_set_read_only(GSingletonCandidate *candidate)
-{
- GList *processed; /* Suivi des traitements */
-
- processed = NULL;
-
- _g_singleton_candidate_set_read_only(candidate, &processed);
-
- assert(processed != NULL);
+ }
- g_list_free(processed);
-
-}
+ g_singleton_candidate_update_inner_instances(result, new_children, count);
+ for (i = 0; i < count; i++)
+ {
+ unref_object(G_OBJECT(new_children[i]));
+ unref_object(G_OBJECT(children[i]));
+ }
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* *
-* Description : Indique si le candidat est figé. *
-* *
-* Retour : true si le contenu du candidat ne peut plus être modifié. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ free(new_children);
-bool g_singleton_candidate_is_read_only(const GSingletonCandidate *candidate)
-{
- bool result; /* Etat à retourner */
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ }
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
+ if (children != NULL)
+ free(children);
- result = iface->is_ro(candidate);
+ assert(G_OBJECT_TYPE(result) == G_OBJECT_TYPE(candidate));
return result;
@@ -528,8 +367,8 @@ static void g_singleton_factory_class_init(GSingletonFactoryClass *klass)
static void g_singleton_factory_init(GSingletonFactory *factory)
{
- factory->table = g_hash_table_new_full((GHashFunc)g_singleton_candidate_hash,
- (GEqualFunc)g_singleton_candidate_is_equal,
+ factory->table = g_hash_table_new_full((GHashFunc)g_hashable_object_hash,
+ (GEqualFunc)g_comparable_object_is_equal,
g_object_unref, NULL);
g_mutex_init(&factory->access);
@@ -688,7 +527,7 @@ GSingletonCandidate *g_singleton_factory_get_instance(GSingletonFactory *factory
g_hash_table_add(factory->table, candidate);
#endif
- g_singleton_candidate_set_read_only(candidate);
+ g_singleton_candidate_mark_as_read_only(candidate);
result = candidate;
diff --git a/src/glibext/singleton.h b/src/glibext/singleton.h
index 629687a..11afffd 100644
--- a/src/glibext/singleton.h
+++ b/src/glibext/singleton.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* singleton.h - prototypes pour la réduction du nombre d'instances d'un même type
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,71 +25,36 @@
#define _GLIBEXT_SINGLETON_H
-#include <glib-object.h>
#include <stdbool.h>
-
-/* Définition d'un compacteur d'instances de types (instance) */
-typedef struct _GSingletonFactory GSingletonFactory;
+#include "helpers.h"
/* ------------------ INTERFACE POUR CANDIDAT A UNE CENTRALISATION ------------------ */
-#define G_TYPE_SINGLETON_CANDIDATE (g_singleton_candidate_get_type())
-#define G_SINGLETON_CANDIDATE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SINGLETON_CANDIDATE, GSingletonCandidate))
-#define G_SINGLETON_CANDIDATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SINGLETON_CANDIDATE, GSingletonCandidateIface))
-#define G_IS_SINGLETON_CANDIDATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SINGLETON_CANDIDATE))
-#define G_IS_SINGLETON_CANDIDATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SINGLETON_CANDIDATE))
-#define G_SINGLETON_CANDIDATE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SINGLETON_CANDIDATE, GSingletonCandidateIface))
-
-
-/* Instance d'objet visant à être unique (coquille vide) */
-typedef struct _GSingletonCandidate GSingletonCandidate;
-
-/* Instance d'objet visant à être unique (interface) */
-typedef struct _GSingletonCandidateIface GSingletonCandidateIface;
-
-
-/* Détermine le type d'une interface pour la lecture de binaire. */
-GType g_singleton_candidate_get_type(void) G_GNUC_CONST;
+#define G_TYPE_SINGLETON_CANDIDATE (g_singleton_candidate_get_type())
-/* Fournit une liste de candidats embarqués par un candidat. */
-GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *, size_t *);
+DECLARE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G, SINGLETON_CANDIDATE);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-guint g_singleton_candidate_hash(GSingletonCandidate *);
-
-/* Détermine si deux candidats à l'unicité sont identiques. */
-gboolean g_singleton_candidate_is_equal(GSingletonCandidate *, GSingletonCandidate *);
-
-/* Marque un candidat comme figé. */
-void g_singleton_candidate_set_read_only(GSingletonCandidate *);
/* Indique si le candidat est figé. */
bool g_singleton_candidate_is_read_only(const GSingletonCandidate *);
+/* Crée une copie modifiable d'un object unique. */
+GSingletonCandidate *g_singleton_candidate_dup(const GSingletonCandidate *);
-/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
-
-#define G_TYPE_SINGLETON_FACTORY g_singleton_factory_get_type()
-#define G_SINGLETON_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SINGLETON_FACTORY, GSingletonFactory))
-#define G_IS_SINGLETON_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SINGLETON_FACTORY))
-#define G_SINGLETON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SINGLETON_FACTORY, GSingletonFactoryClass))
-#define G_IS_SINGLETON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SINGLETON_FACTORY))
-#define G_SINGLETON_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SINGLETON_FACTORY, GSingletonFactoryClass))
+/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
-/* Définition d'un compacteur d'instances de types (classe) */
-typedef struct _GSingletonFactoryClass GSingletonFactoryClass;
+#define G_TYPE_SINGLETON_FACTORY (g_singleton_factory_get_type())
+DECLARE_GTYPE(GSingletonFactory, g_singleton_factory, G, SINGLETON_FACTORY);
-/* Indique le type défini pour une mémoire de types d'objets. */
-GType g_singleton_factory_get_type(void);
/* Crée un compacteur d'instances de types. */
GSingletonFactory *g_singleton_factory_new(void);
diff --git a/src/analysis/storage/storage-int.h b/src/glibext/storage-int.h
index 4883aa8..d89e1c8 100644
--- a/src/analysis/storage/storage-int.h
+++ b/src/glibext/storage-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * storage.h - prototypes internes pour la conservation sur disque d'objets construits
+ * storage-int.h - prototypes internes pour la conservation sur disque d'objets construits
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,13 @@
*/
-#ifndef _ANALYSIS_STORAGE_STORAGE_INT_H
-#define _ANALYSIS_STORAGE_STORAGE_INT_H
+#ifndef _GLIBEXT_STORAGE_INT_H
+#define _GLIBEXT_STORAGE_INT_H
#include "storage.h"
+#include "tpmem.h"
+#include "../common/szbin.h"
@@ -44,9 +46,12 @@ struct _GObjectStorage
{
GObject parent; /* A laisser en premier */
- GTypeMemory *tpmem; /* Mémorisation de types */
+ sized_binary_t type; /* Type de conservation */
+ uint8_t version; /* Version correspondante */
+
+ sized_binary_t uid; /* Identifiant de distinction */
- char *hash; /* Empreinte du contenu */
+ GTypeMemory *tpmem; /* Mémorisation de types */
storage_backend_t *backends; /* Gestionnaires existants */
size_t count; /* Quantité de gestionnaires */
@@ -62,5 +67,9 @@ struct _GObjectStorageClass
};
+/* Met en place un support d'une conservation d'objets en place. */
+bool g_object_storage_create(GObjectStorage *, const char *, uint8_t, const char *);
+
+
-#endif /* _ANALYSIS_STORAGE_STORAGE_INT_H */
+#endif /* _GLIBEXT_STORAGE_INT_H */
diff --git a/src/analysis/storage/storage.c b/src/glibext/storage.c
index 610a0f6..0a3c4e7 100644
--- a/src/analysis/storage/storage.c
+++ b/src/glibext/storage.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* storage.c - conservation hors mémoire d'objets choisis
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,20 +28,23 @@
#include <malloc.h>
#include <string.h>
#include <unistd.h>
-#include <stdarg.h>
+#include <zip.h>
#include "storage-int.h"
-#include "../db/misc/rlestr.h"
-#include "../../common/io.h"
-#include "../../common/leb128.h"
-#include "../../common/pathname.h"
-#include "../../core/logs.h"
+#include "../common/cpp.h"
+#include "../common/pathname.h"
+#include "../core/logs.h"
-
-#define STORAGE_MAGIC "CSTR"
-#define STORAGE_NUMBER "\x00\x01"
+/**
+ * Historique du format :
+ *
+ * - 09/03/25 : 1.0 (version initiale)
+ *
+ */
+#define STORAGE_MAGIC "COBSTR"
+#define STORAGE_NUMBER "\x01\x00"
/* Initialise la classe des conservations d'objets en place. */
@@ -51,10 +54,13 @@ static void g_object_storage_class_init(GObjectStorageClass *);
static void g_object_storage_init(GObjectStorage *);
/* Supprime toutes les références externes. */
-static void g_object_storage_dispose(GObjectStorage *);
+static void g_object_storage_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_object_storage_finalize(GObjectStorage *);
+static void g_object_storage_finalize(GObject *);
+
+/* Assure l'inexistence d'un groupe avec un nom donné. */
+static bool g_object_storage_has_no_backend_named(GObjectStorage *, const char *);
/* Retrouve l'encadrement pour un nouveau groupe d'objets. */
static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const char *);
@@ -62,11 +68,8 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const
/* Ajoute le support d'un nouveau groupe d'objets construits. */
static bool g_object_storage_add_backend(GObjectStorage *, const char *, storage_backend_t **);
-/* Extrait d'un tampon des enregistrements spécifiques. */
-static bool g_object_storage_load_backend(GObjectStorage *, packed_buffer_t *);
-
-/* Place dans un tampon les données liées à des enregistrements. */
-static bool pack_storage_backend(const storage_backend_t *, packed_buffer_t *);
+/* Charge un objet à partir de données rassemblées. */
+static GSerializableObject *g_object_storage_load_object_unlocked(GObjectStorage *, const char *, off64_t);
@@ -92,8 +95,8 @@ static void g_object_storage_class_init(GObjectStorageClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_object_storage_dispose;
- object->finalize = (GObjectFinalizeFunc)g_object_storage_finalize;
+ object->dispose = g_object_storage_dispose;
+ object->finalize = g_object_storage_finalize;
}
@@ -112,9 +115,12 @@ static void g_object_storage_class_init(GObjectStorageClass *klass)
static void g_object_storage_init(GObjectStorage *storage)
{
- storage->tpmem = g_type_memory_new();
+ init_sized_binary(&storage->type);
+ storage->version = 0;
- storage->hash = NULL;
+ init_sized_binary(&storage->uid);
+
+ storage->tpmem = g_type_memory_new();
storage->backends = NULL;
storage->count = 0;
@@ -125,7 +131,7 @@ static void g_object_storage_init(GObjectStorage *storage)
/******************************************************************************
* *
-* Paramètres : storage = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -135,18 +141,22 @@ static void g_object_storage_init(GObjectStorage *storage)
* *
******************************************************************************/
-static void g_object_storage_dispose(GObjectStorage *storage)
+static void g_object_storage_dispose(GObject *object)
{
+ GObjectStorage *storage; /* Version spécialisée */
+
+ storage = G_OBJECT_STORAGE(object);
+
g_clear_object(&storage->tpmem);
- G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(G_OBJECT(storage));
+ G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : storage = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -156,18 +166,27 @@ static void g_object_storage_dispose(GObjectStorage *storage)
* *
******************************************************************************/
-static void g_object_storage_finalize(GObjectStorage *storage)
+static void g_object_storage_finalize(GObject *object)
{
+ GObjectStorage *storage; /* Version spécialisée */
size_t i; /* Boucle de parcours */
storage_backend_t *backend; /* Gestionnaire à manipuler */
int ret; /* Bilan d'un appel */
+ storage = G_OBJECT_STORAGE(object);
+
g_mutex_lock(&storage->mutex);
for (i = 0; i < storage->count; i++)
{
backend = &storage->backends[i];
+ /**
+ * Chargement incomplet depuis g_object_storage_load().
+ */
+ if (backend->name == NULL)
+ break;
+
if (backend->fd != -1)
close(backend->fd);
else
@@ -193,17 +212,20 @@ static void g_object_storage_finalize(GObjectStorage *storage)
g_mutex_clear(&storage->mutex);
- if (storage->hash != NULL)
- free(storage->hash);
+ exit_sized_binary(&storage->type);
+
+ exit_sized_binary(&storage->uid);
- G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(G_OBJECT(storage));
+ G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(object);
}
/******************************************************************************
* *
-* Paramètres : loaded = contenu binaire à associer. *
+* Paramètres : type = type global à indiquer dans une conservation. *
+* version = numéro de version associé. *
+* uid = identifiant arbitraire mais unique pour distinguer.*
* *
* Description : Crée le support d'une conservation d'objets en place. *
* *
@@ -213,13 +235,14 @@ static void g_object_storage_finalize(GObjectStorage *storage)
* *
******************************************************************************/
-GObjectStorage *g_object_storage_new(const char *hash)
+GObjectStorage *g_object_storage_new(const char *type, uint8_t version, const char *uid)
{
GObjectStorage *result; /* Structure à retourner */
result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL);
- result->hash = strdup(hash);
+ if (!g_object_storage_create(result, type, version, uid))
+ g_clear_object(&result);
return result;
@@ -228,7 +251,39 @@ GObjectStorage *g_object_storage_new(const char *hash)
/******************************************************************************
* *
-* Paramètres : pbuf = zone tampon à lire. *
+* Paramètres : storage = stockage d'objets à initialiser. *
+* type = type global à indiquer dans une conservation. *
+* version = numéro de version associé. *
+* uid = identifiant arbitraire mais unique pour distinguer.*
+* *
+* Description : Met en place un support d'une conservation d'objets en place.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_object_storage_create(GObjectStorage *storage, const char *type, uint8_t version, const char *uid)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ dup_into_sized_binary(&storage->type, type, strlen(type));
+
+ storage->version = version;
+
+ dup_into_sized_binary(&storage->uid, uid, strlen(uid) + 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = fichier de source à traiter. *
* *
* Description : Charge le support d'une conservation d'objets en place. *
* *
@@ -238,140 +293,297 @@ GObjectStorage *g_object_storage_new(const char *hash)
* *
******************************************************************************/
-GObjectStorage *g_object_storage_load(packed_buffer_t *pbuf)
+GObjectStorage *g_object_storage_load(const char *filename)
{
GObjectStorage *result; /* Structure à retourner */
- char header[6]; /* Entête attendue des données */
+ GObjectStorage *storage; /* Structure en construction */
+ int err; /* Eventuel code d'erreur */
+ zip_t *archive; /* Archive ZIP à manipuler */
+ zip_error_t error; /* Suivi des erreurs obtenues */
+ char *tpmem_filename; /* Chemin d'accès pour types */
+ zip_int64_t entries_count; /* Nombre d'éléments ZIP */
+ void *data; /* Données (décompressées) */
+ zip_stat_t stats; /* Information sur les données */
+ zip_file_t *file; /* Echantillon à extraire */
+ zip_int64_t got; /* Nombre d'octets lus */
+ int ret; /* Bilan d'un appel */
+ const void *pos; /* Tête de lecture */
+ const void *max; /* Fin des données lisibles */
bool status; /* Bilan d'une extraction */
- rle_string str; /* Chaîne à conserver */
- uleb128_t count; /* Nombre de groupes à charger */
- uleb128_t i; /* Boucle de parcours */
+ char *prefix; /* Début de nom de fichier */
+ int fd; /* Descripteur de flux ouvert */
+ off_t moved; /* Nouvelle position établie */
+ zip_int64_t i; /* Boucle de parcours */
+ storage_backend_t *backend; /* Informations à intégrer */
+ const char *slash; /* Pointeur vers un caractère /*/
result = NULL;
- status = extract_packed_buffer(pbuf, header, 6, false);
- if (!status) goto quick_exit;
+ storage = g_object_new(G_TYPE_OBJECT_STORAGE, NULL);
- if (strncmp(header, STORAGE_MAGIC STORAGE_NUMBER, 6) != 0)
- goto quick_exit;
+ archive = zip_open(filename, ZIP_RDONLY, &err);
+ if (archive == NULL)
+ {
+ zip_error_init_with_code(&error, err);
+ LOG_ERROR_ZIP("zip_open", &error);
+ goto exit;
+ }
+
+ zip_error_init(&error);
+
+ tpmem_filename = NULL;
+
+ /* Validation du nombre d'entrées */
+
+ entries_count = zip_get_num_entries(archive, ZIP_FL_UNCHANGED);
- setup_empty_rle_string(&str);
+ if (entries_count < 2)
+ goto exit_with_archive;
- status = unpack_rle_string(&str, pbuf);
- if (!status) goto quick_exit;
+ data = NULL;
- if (get_rle_string(&str) == NULL)
+ /* Extraction de la partie de contrôle */
+
+ ret = zip_stat_index(archive, 0, ZIP_FL_UNCHANGED, &stats);
+ if (ret != 0)
{
- exit_rle_string(&str);
- goto quick_exit;
+ LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive));
+ goto exit_with_archive;
}
- result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL);
-
- result->hash = strdup(get_rle_string(&str));
+ if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE))
+ goto exit_with_archive;
- exit_rle_string(&str);
+ if (strcmp(stats.name, "control") != 0)
+ goto exit_with_archive;
- status = g_type_memory_load_types(result->tpmem, pbuf);
- if (!status) goto exit_while_loading;
+ if (stats.size < (6 + 2 + 1 + 1 + 1))
+ goto exit_with_archive;
- status = unpack_uleb128(&count, pbuf);
+ file = zip_fopen_index(archive, 0, ZIP_FL_UNCHANGED);
+ if (file == NULL)
+ {
+ LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
- for (i = 0; i < count && status; i++)
- status = g_object_storage_load_backend(result, pbuf);
+ data = malloc(stats.size);
- exit_while_loading:
+ got = zip_fread(file, data, stats.size);
- if (!status)
+ ret = zip_fclose(file);
+ if (ret != 0)
{
- g_object_unref(G_OBJECT(result));
- result = NULL;
+ zip_error_set(&error, ret, 0);
+ LOG_ERROR_ZIP("zip_fclose", &error);
+ goto exit_with_data;
}
- quick_exit:
+ if (got != stats.size)
+ goto exit_with_data;
- return result;
+ if (memcmp(data, STORAGE_MAGIC, 6) != 0)
+ goto exit_with_data;
-}
+ if (memcmp(((uint8_t *)data) + 6, STORAGE_NUMBER, 2) != 0)
+ goto exit_with_data;
+ pos = (uint8_t *)data + 8;
+ max = (uint8_t *)data + got;
-/******************************************************************************
-* *
-* Paramètres : storage = gestionnaire de conservations à manipuler. *
-* pbuf = zone tampon à remplir. [OUT] *
-* *
-* Description : Sauvegarde le support d'une conservation d'objets en place. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ status = unpack_sized_binary(&storage->type, &pos, max);
+ if (!status) goto exit_with_data;
-bool g_object_storage_store(GObjectStorage *storage, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- rle_string str; /* Chaîne à conserver */
- size_t i; /* Boucle de parcours */
+ if (pos >= max)
+ goto exit_with_data;
- result = extend_packed_buffer(pbuf, STORAGE_MAGIC STORAGE_NUMBER, 6, false);
+ storage->version = *(uint8_t *)pos;
+ pos = (uint8_t *)pos + 1;
- if (result)
+ unpack_sized_binary_as_string(&storage->uid, &pos, max);
+ if (!status) goto exit_with_data;
+
+ if (pos != max)
+ goto exit_with_data;
+
+ free(data);
+ data = NULL;
+
+ /* Extraction de la conservation des types */
+
+ ret = zip_stat_index(archive, 1, ZIP_FL_UNCHANGED, &stats);
+ if (ret != 0)
{
- init_static_rle_string(&str, storage->hash);
+ LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
- result = pack_rle_string(&str, pbuf);
+ if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE))
+ goto exit_with_archive;
- exit_rle_string(&str);
+ if (strcmp(stats.name, "types") != 0)
+ goto exit_with_archive;
+ file = zip_fopen_index(archive, 1, ZIP_FL_UNCHANGED);
+ if (file == NULL)
+ {
+ LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive));
+ goto exit_with_archive;
}
- g_mutex_lock(&storage->mutex);
+ data = malloc(stats.size);
- if (result)
- result = g_type_memory_store_types(storage->tpmem, pbuf);
+ got = zip_fread(file, data, stats.size);
- if (result)
- result = pack_uleb128((uleb128_t []){ storage->count }, pbuf);
+ ret = zip_fclose(file);
+ if (ret != 0)
+ {
+ zip_error_set(&error, ret, 0);
+ LOG_ERROR_ZIP("zip_fclose", &error);
+ goto exit_with_data;
+ }
- for (i = 0; i < storage->count && result; i++)
- result = pack_storage_backend(&storage->backends[i], pbuf);
+ asprintf(&prefix, "%s-types", storage->uid.static_data);
- g_mutex_unlock(&storage->mutex);
+ fd = make_tmp_file(prefix, "cache", &tpmem_filename);
- return result;
+ free(prefix);
-}
+ if (fd == -1)
+ goto exit_with_data;
+ status = safe_write(fd, data, stats.size);
+ if (!status)
+ {
+ close(fd);
+ goto exit_with_data;
+ }
-/******************************************************************************
-* *
-* Paramètres : storage = gestionnaire de conservations à compléter. *
-* name = désignation d'un nouveau groupe d'objets. *
-* *
-* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. *
-* *
-* Retour : Informations liées à un groupe ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ moved = lseek(fd, 0, SEEK_SET);
+ if (moved == ((off_t)-1))
+ {
+ LOG_ERROR_N("lseek");
+ close(fd);
+ goto exit_with_data;
+ }
-static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name)
-{
- storage_backend_t *result; /* Encadrement à retourner */
- size_t i; /* Boucle de parcours */
+ status = g_type_memory_load(storage->tpmem, fd);
- assert(!g_mutex_trylock(&storage->mutex));
+ close(fd);
- for (i = 0; i < storage->count; i++)
- if (strcmp(storage->backends[i].name, name) == 0)
- break;
+ if (!status)
+ goto exit_with_data;
- if (i == storage->count)
- result = NULL;
- else
- result = &storage->backends[i];
+ free(data);
+ data = NULL;
+
+ /* Extraction des différents objects restants */
+
+ if (entries_count > 2)
+ {
+ storage->count = entries_count - 2;
+ storage->backends = calloc(storage->count, sizeof(storage_backend_t));
+
+ for (i = 2; i < entries_count; i++)
+ {
+ backend = &storage->backends[i - 2];
+
+ ret = zip_stat_index(archive, i, ZIP_FL_UNCHANGED, &stats);
+ if (ret != 0)
+ {
+ LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE))
+ goto exit_with_archive;
+
+ if (strncmp(stats.name, SL("backends/")) != 0)
+ goto exit_with_archive;
+
+ slash = strchr(stats.name, '/');
+
+ if (slash == NULL)
+ goto exit_with_archive;
+
+ if (strchr(slash + 1, '/') != NULL)
+ goto exit_with_archive;
+
+ if (!g_object_storage_has_no_backend_named(storage, slash + 1))
+ goto exit_with_archive;
+
+ file = zip_fopen_index(archive, i, ZIP_FL_UNCHANGED);
+ if (file == NULL)
+ {
+ LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ data = malloc(stats.size);
+
+ got = zip_fread(file, data, stats.size);
+
+ ret = zip_fclose(file);
+ if (ret != 0)
+ {
+ zip_error_set(&error, ret, 0);
+ LOG_ERROR_ZIP("zip_fclose", &error);
+ goto exit_with_data;
+ }
+
+ backend->name = strdup(slash + 1);
+
+ asprintf(&prefix, "%s-%s", storage->uid.static_data, backend->name);
+
+ backend->fd = make_tmp_file(prefix, "cache", &backend->filename);
+
+ free(prefix);
+
+ if (backend->fd == -1)
+ goto exit_with_data;
+
+ status = safe_write(backend->fd, data, stats.size);
+ if (!status) goto exit_with_data;
+
+ moved = lseek(backend->fd, 0, SEEK_SET);
+ if (moved == ((off_t)-1))
+ {
+ LOG_ERROR_N("lseek");
+ goto exit_with_data;
+ }
+
+ free(data);
+ data = NULL;
+
+ }
+
+ }
+
+ /* Clôture des opérations */
+
+ result = storage;
+ ref_object(storage);
+
+ exit_with_data:
+
+ if (data != NULL)
+ free(data);
+
+ exit_with_archive:
+
+ ret = zip_close(archive);
+
+ if (ret != 0)
+ LOG_ERROR_ZIP("zip_close", zip_get_error(archive));
+
+ if (tpmem_filename != NULL)
+ unlink(tpmem_filename);
+
+ zip_error_fini(&error);
+
+ exit:
+
+ unref_object(storage);
return result;
@@ -380,11 +592,10 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage,
/******************************************************************************
* *
-* Paramètres : storage = gestionnaire de conservations à compléter. *
-* name = désignation d'un nouveau groupe d'objets. *
-* backend = support mis en place pour les enregistrements. *
+* Paramètres : storage = gestionnaire de conservations à manipuler. *
+* filename = fichier de destination à constituer. *
* *
-* Description : Ajoute le support d'un nouveau groupe d'objets construits. *
+* Description : Sauvegarde le support d'une conservation d'objets en place. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -392,46 +603,199 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage,
* *
******************************************************************************/
-static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend)
+bool g_object_storage_store(GObjectStorage *storage, const char *filename)
{
bool result; /* Bilan à retourner */
+ int err; /* Eventuel code d'erreur */
+ zip_t *archive; /* Archive ZIP à manipuler */
+ zip_error_t error; /* Suivi des erreurs obtenues */
+ char *tpmem_filename; /* Chemin d'accès pour types */
+ void *type_buf; /* Données pour le type */
+ size_t type_buflen; /* Quantité de ces données */
+ void *uid_buf; /* Données pour l'identifiant */
+ size_t uid_buflen; /* Quantité de ces données */
+ size_t control_len; /* Taille des premières données*/
+ uint8_t *control; /* Premières données du fichier*/
+ zip_source_t *zip_data; /* Données ZIP à intégrer */
+ zip_int64_t index; /* Nouvel index du contenu */
+ int ret; /* Bilan d'un appel */
char *prefix; /* Début de nom de fichier */
- char *filename; /* Chemin d'accès aux données */
int fd; /* Descripteur de flux ouvert */
+ bool status; /* Bilan d'une écriture */
+ size_t i; /* Boucle de parcours */
+ char *zip_name; /* Destination pour l'archive */
result = false;
- *backend = NULL;
+ archive = zip_open(filename, ZIP_CREATE | ZIP_TRUNCATE, &err);
+ if (archive == NULL)
+ {
+ zip_error_init_with_code(&error, err);
+ LOG_ERROR_ZIP("zip_open", &error);
+ goto exit;
+ }
- assert(!g_mutex_trylock(&storage->mutex));
+ zip_error_init(&error);
- if (g_object_storage_find_backend(storage, name) != NULL)
- goto exit;
+ tpmem_filename = NULL;
- /* Préparatifs */
+ /* Fichier de contrôle */
- asprintf(&prefix, "%s-%s", storage->hash, name);
+ type_buf = pack_sized_binary(&storage->type, &type_buflen);
- fd = make_tmp_file(prefix, "cache", &filename);
+ uid_buf = pack_sized_binary_as_string(&storage->uid, &uid_buflen);
+
+ assert((sizeof(STORAGE_MAGIC) - 1 + sizeof(STORAGE_NUMBER) - 1) == 8);
+
+ control_len = 8 + type_buflen + 1 + uid_buflen;
+ control = malloc(control_len * sizeof(uint8_t));
+
+ memcpy(control, STORAGE_MAGIC, 6);
+ memcpy(control + 6, STORAGE_NUMBER, 2);
+
+ memcpy(control + 8, type_buf, type_buflen);
+
+ control[8 + type_buflen] = storage->version;
+
+ memcpy(control + 8 + type_buflen + 1, uid_buf, uid_buflen);
+
+ zip_data = zip_source_buffer_create(control, control_len, 0, &error);
+ if (zip_data == NULL)
+ {
+ LOG_ERROR_ZIP("zip_source_buffer_create", &error);
+ goto exit_with_control;
+ }
+
+ index = zip_file_add(archive, "control", zip_data, ZIP_FL_ENC_UTF_8);
+ if (index == -1)
+ {
+ zip_source_free(zip_data);
+ LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive));
+ goto exit_with_control;
+ }
+
+ ret = zip_set_file_compression(archive, index, ZIP_CM_STORE, 0 /* comp_flags */);
+ if (ret == -1)
+ {
+ LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive));
+ goto exit_with_control;
+ }
+
+ /* Composants de la conservation */
+
+ g_mutex_lock(&storage->mutex);
+
+ /* Conservation des types */
+
+ asprintf(&prefix, "%s-types", storage->uid.static_data);
+
+ fd = make_tmp_file(prefix, "cache", &tpmem_filename);
free(prefix);
if (fd == -1)
- goto exit;
+ goto exit_with_lock;
- /* Inscription en bonne et due forme */
+ status = g_type_memory_store(storage->tpmem, fd);
- storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t));
+ close(fd);
- *backend = &storage->backends[storage->count - 1];
+ if (!status)
+ goto exit_with_lock;
- (*backend)->name = strdup(name);
+ zip_data = zip_source_file_create(tpmem_filename, 0, -1 /* ZIP_LENGTH_TO_END */, &error);
+ if (zip_data == NULL)
+ {
+ LOG_ERROR_ZIP("zip_source_file_create", &error);
+ goto exit_with_lock;
+ }
- (*backend)->filename = filename;
- (*backend)->fd = fd;
+ index = zip_file_add(archive, "types", zip_data, ZIP_FL_ENC_UTF_8);
+ if (index == -1)
+ {
+ zip_source_free(zip_data);
+ LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ ret = zip_set_file_compression(archive, index, ZIP_CM_DEFLATE, 9 /* comp_flags */);
+ if (ret == -1)
+ {
+ LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ /* Conservation des objets */
+
+ for (i = 0; i < storage->count; i++)
+ {
+ zip_data = zip_source_file_create(storage->backends[i].filename, 0, -1 /* ZIP_LENGTH_TO_END */, &error);
+ if (zip_data == NULL)
+ {
+ LOG_ERROR_ZIP("zip_source_file_create", &error);
+ goto exit_with_lock;
+ }
+
+ /**
+ * Pas besoin de distinguer les chemins UNIX et Windows ici.
+ *
+ * Cf. https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT :
+ *
+ * 4.4.17 file name: (Variable)
+ *
+ * The path stored MUST NOT contain a drive or
+ * device letter, or a leading slash. All slashes
+ * MUST be forward slashes '/' as opposed to
+ * backwards slashes '\' for compatibility with Amiga
+ * and UNIX file systems etc. If input came from standard
+ * input, there is no file name field.
+ *
+ */
+
+ asprintf(&zip_name, "backends/%s", storage->backends[i].name);
+
+ index = zip_file_add(archive, zip_name, zip_data, ZIP_FL_ENC_UTF_8);
+
+ free(zip_name);
+
+ if (index == -1)
+ {
+ zip_source_free(zip_data);
+ LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ ret = zip_set_file_compression(archive, index, ZIP_CM_DEFLATE, 9 /* comp_flags */);
+ if (ret == -1)
+ {
+ LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ }
result = true;
+ /* Clôture des opérations */
+
+ exit_with_lock:
+
+ g_mutex_unlock(&storage->mutex);
+
+ exit_with_control:
+
+ ret = zip_close(archive);
+
+ if (ret != 0)
+ LOG_ERROR_ZIP("zip_close", zip_get_error(archive));
+
+ free(control);
+
+ if (tpmem_filename != NULL)
+ unlink(tpmem_filename);
+
+ zip_error_fini(&error);
+
exit:
return result;
@@ -441,71 +805,67 @@ static bool g_object_storage_add_backend(GObjectStorage *storage, const char *na
/******************************************************************************
* *
-* Paramètres : storage = gestionnaire de conservations à compléter. *
-* pbuf = zone tampon à lire. *
+* Paramètres : storage = gestionnaire de conservations à consulter. *
+* name = désignation d'un nouveau groupe d'objets. *
* *
-* Description : Extrait d'un tampon des enregistrements spécifiques. *
+* Description : Assure l'inexistence d'un groupe avec un nom donné. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan des recherches. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer_t *pbuf)
+static bool g_object_storage_has_no_backend_named(GObjectStorage *storage, const char *name)
{
bool result; /* Bilan à retourner */
- rle_string str; /* Chaîne à conserver */
- bool status; /* Bilan de lecture de contenu */
- storage_backend_t *backend; /* Informations à intégrer */
- uleb128_t length; /* Taille des données à charger*/
- off_t moved; /* Nouvelle position établie */
-
- result = false;
-
- g_mutex_lock(&storage->mutex);
-
- /* Récupération du nom et création du support */
-
- setup_empty_rle_string(&str);
+ size_t i; /* Boucle de parcours */
- status = unpack_rle_string(&str, pbuf);
- if (!status) goto exit;
+ result = true;
- if (get_rle_string(&str) == NULL)
+ for (i = 0; i < storage->count && result; i++)
{
- exit_rle_string(&str);
- goto exit;
- }
-
- status = g_object_storage_add_backend(storage, get_rle_string(&str), &backend);
+ if (storage->backends[i].name == NULL)
+ break;
- exit_rle_string(&str);
+ if (strcmp(storage->backends[i].name, name) == 0)
+ result = false;
- if (!status) goto exit;
+ }
- /* Récupération du contenu */
+ return result;
- status = unpack_uleb128(&length, pbuf);
- if (!status) goto exit;
+}
- status = safe_write(backend->fd, pbuf->data + pbuf->pos, length);
- if (!status) goto exit;
- advance_packed_buffer(pbuf, length);
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire de conservations à compléter. *
+* name = désignation d'un nouveau groupe d'objets. *
+* *
+* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. *
+* *
+* Retour : Informations liées à un groupe ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- moved = lseek(backend->fd, 0, SEEK_SET);
- if (moved == ((off_t)-1))
- {
- LOG_ERROR_N("lseek");
- goto exit;
- }
+static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name)
+{
+ storage_backend_t *result; /* Encadrement à retourner */
+ size_t i; /* Boucle de parcours */
- result = true;
+ assert(!g_mutex_trylock(&storage->mutex));
- exit:
+ for (i = 0; i < storage->count; i++)
+ if (strcmp(storage->backends[i].name, name) == 0)
+ break;
- g_mutex_unlock(&storage->mutex);
+ if (i == storage->count)
+ result = NULL;
+ else
+ result = &storage->backends[i];
return result;
@@ -514,10 +874,11 @@ static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer
/******************************************************************************
* *
-* Paramètres : backend = stockage des enregistrements spécifiques. *
-* pbuf = zone tampon à remplir. [OUT] *
+* Paramètres : storage = gestionnaire de conservations à compléter. *
+* name = désignation d'un nouveau groupe d'objets. *
+* backend = support mis en place pour les enregistrements. *
* *
-* Description : Place dans un tampon les données liées à des enregistrements.*
+* Description : Ajoute le support d'un nouveau groupe d'objets construits. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -525,72 +886,45 @@ static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer
* *
******************************************************************************/
-static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer_t *pbuf)
+static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend)
{
bool result; /* Bilan à retourner */
- rle_string str; /* Chaîne à conserver */
- bool status; /* Bilan de lecture de contenu */
- off_t current; /* Position courante */
- off_t moved; /* Nouvelle position établie */
- void *data; /* Données à transférer */
+ char *prefix; /* Début de nom de fichier */
+ char *filename; /* Chemin d'accès aux données */
+ int fd; /* Descripteur de flux ouvert */
result = false;
- /* Inscription du nom */
+ *backend = NULL;
- init_static_rle_string(&str, backend->name);
+ assert(!g_mutex_trylock(&storage->mutex));
- status = pack_rle_string(&str, pbuf);
+ if (g_object_storage_find_backend(storage, name) != NULL)
+ goto exit;
- exit_rle_string(&str);
+ /* Préparatifs */
- if (!status) goto exit;
+ asprintf(&prefix, "%s-%s", storage->uid.static_data, name);
- /* Inscription du contenu */
+ fd = make_tmp_file(prefix, "cache", &filename);
- current = lseek(backend->fd, 0, SEEK_CUR);
- if (current == ((off_t)-1))
- {
- LOG_ERROR_N("lseek");
- goto exit;
- }
+ free(prefix);
- moved = lseek(backend->fd, 0, SEEK_SET);
- if (moved == ((off_t)-1))
- {
- LOG_ERROR_N("lseek");
+ if (fd == -1)
goto exit;
- }
- data = malloc(current);
- if (data == NULL)
- {
- LOG_ERROR_N("malloc");
- goto restore;
- }
-
- status = safe_read(backend->fd, data, current);
- if (!status) goto free_mem;
-
- status = pack_uleb128((uleb128_t []){ current }, pbuf);
- if (!status) goto free_mem;
-
- status = extend_packed_buffer(pbuf, data, current, false);
+ /* Inscription en bonne et due forme */
- free_mem:
+ storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t));
- free(data);
+ *backend = &storage->backends[storage->count - 1];
- restore:
+ (*backend)->name = strdup(name);
- moved = lseek(backend->fd, current, SEEK_SET);
- if (moved == ((off_t)-1))
- {
- LOG_ERROR_N("lseek");
- goto exit;
- }
+ (*backend)->filename = filename;
+ (*backend)->fd = fd;
- result = status;
+ result = true;
exit:
@@ -602,7 +936,7 @@ static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer
/******************************************************************************
* *
* Paramètres : storage = gestionnaire à manipuler. *
-* name = désignation d'un nouveau groupe d'objets. *
+* name = désignation d'un groupe d'objets à consulter. *
* pos = tête de lecture avant écriture. *
* *
* Description : Charge un objet à partir de données rassemblées. *
@@ -613,56 +947,44 @@ static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer
* *
******************************************************************************/
-GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos)
+static GSerializableObject *g_object_storage_load_object_unlocked(GObjectStorage *storage, const char *name, off64_t pos)
{
GSerializableObject *result; /* Instance à retourner */
- bool status; /* Bilan d'une opération */
storage_backend_t *backend; /* Informations à consulter */
- packed_buffer_t pbuf; /* Tampon des données à lire */
off64_t new; /* Nouvelle position de lecture*/
+ bool status; /* Bilan d'une opération */
result = NULL;
- /* Chargement */
-
- status = false;
+ assert(!g_mutex_trylock(&storage->mutex));
- g_mutex_lock(&storage->mutex);
+ /* Chargement */
backend = g_object_storage_find_backend(storage, name);
+ if (backend == NULL) goto exit;
- if (backend != NULL)
+ new = lseek64(backend->fd, pos, SEEK_SET);
+ if (new == (off_t)-1)
{
- new = lseek64(backend->fd, pos, SEEK_SET);
-
- if (new == pos)
- {
- init_packed_buffer(&pbuf);
- status = read_packed_buffer(&pbuf, backend->fd);
- }
-
+ LOG_ERROR_N("lseek64");
+ goto exit;
}
- g_mutex_unlock(&storage->mutex);
-
- if (!status)
- goto exit;
+ assert (new == pos);
/* Phase de conversion */
- result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object(storage->tpmem, &pbuf));
+ result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object_from_gtype(storage->tpmem, backend->fd));
if (result)
{
- status = g_serializable_object_load(result, storage, &pbuf);
+ status = g_serializable_object_load(result, storage, backend->fd);
if (!status)
g_clear_object(&result);
}
- exit_packed_buffer(&pbuf);
-
exit:
return result;
@@ -673,10 +995,10 @@ GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const
/******************************************************************************
* *
* Paramètres : storage = gestionnaire à manipuler. *
-* name = désignation d'un nouveau groupe d'objets. *
-* pbuf = zone tampon à parcourir. *
+* name = désignation d'un groupe d'objets à consulter. *
+* pos = tête de lecture avant écriture. *
* *
-* Description : Charge un objet interne à partir de données rassemblées. *
+* Description : Charge un objet à partir de données rassemblées. *
* *
* Retour : Objet restauré en mémoire ou NULL en cas d'échec. *
* *
@@ -684,18 +1006,15 @@ GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const
* *
******************************************************************************/
-GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf)
+GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos)
{
GSerializableObject *result; /* Instance à retourner */
- uint64_t pos; /* Localisation des données */
- bool status; /* Bilan d'une opération */
- result = NULL;
+ g_mutex_lock(&storage->mutex);
- status = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true);
+ result = g_object_storage_load_object_unlocked(storage, name, pos);
- if (status)
- result = g_object_storage_load_object(storage, name, pos);
+ g_mutex_unlock(&storage->mutex);
return result;
@@ -704,60 +1023,70 @@ GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, con
/******************************************************************************
* *
-* Paramètres : storage = gestionnaire à manipuler. *
-* name = désignation d'un nouveau groupe d'objets. *
-* pbuf = zone tampon à parcourir. *
-* expected = type d'objet attendu. *
-* ... = élément restauré ou NULL en cas d'échec. [OUT] *
+* Paramètres : storage = gestionnaire à manipuler. *
+* fd = flux de données de l'objet courant. *
+* name = désignation du groupe de l'objets à extraire. *
* *
-* Description : Charge un objet interne à partir de données rassemblées. *
+* Description : Charge un objet interne à partir d'une référence embarquée. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Objet restauré en mémoire ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf, GType expected, ...)
+GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, int fd, const char *name)
{
- bool result; /* Bilan d'une opération */
- uint64_t pos; /* Localisation des données */
- GSerializableObject *instance; /* Objet rechargé à valider */
- va_list ap; /* Liste d'arguments variables */
- void **object; /* Lieu d'enregistrement final */
+ GSerializableObject *result; /* Instance à retourner */
+ storage_backend_t *backend; /* Informations à consulter */
+ uleb128_t pos; /* Localisation des données */
+ bool status; /* Bilan d'une opération */
+ off64_t saved; /* Sauvegarde de position */
+ off64_t new; /* Nouvelle position de lecture*/
- result = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true);
+ result = NULL;
- if (result)
- {
- if (pos == 0)
- *object = NULL;
+ g_mutex_lock(&storage->mutex);
- else
- {
- instance = g_object_storage_load_object(storage, name, pos);
+ /* Récupération de la position */
- result = G_TYPE_CHECK_INSTANCE_TYPE(instance, expected);
+ backend = g_object_storage_find_backend(storage, name);
+ if (backend == NULL) goto exit;
- if (result)
- {
- va_start(ap, expected);
+ status = load_uleb128(&pos, backend->fd);
+ if (!status) goto exit;
- object = va_arg(ap, void **);
+ saved = lseek64(backend->fd, 0, SEEK_CUR);
+ if (saved == (off_t)-1)
+ {
+ LOG_ERROR_N("lseek64");
+ goto exit;
+ }
- *object = instance;
+ /* Chargement */
- va_end(ap);
+ result = g_object_storage_load_object_unlocked(storage, name, pos);
- }
+ if (result == NULL) goto exit;
- else
- g_clear_object(&instance);
+ /* Restauration de la position courante */
- }
+ new = lseek64(backend->fd, saved, SEEK_SET);
+ if (new == (off_t)-1)
+ {
+ LOG_ERROR_N("lseek64");
+
+ g_clear_object(&result);
+ goto exit;
}
+ assert (new == saved);
+
+ exit:
+
+ g_mutex_unlock(&storage->mutex);
+
return result;
}
@@ -766,7 +1095,7 @@ bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name,
/******************************************************************************
* *
* Paramètres : storage = gestionnaire à manipuler. *
-* name = désignation d'un nouveau groupe d'objets. *
+* name = désignation d'un groupe d'objets, nouveau ou non. *
* object = objet sérialisable à traiter. *
* pos = tête de lecture avant écriture. [OUT] *
* *
@@ -781,22 +1110,9 @@ bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name,
bool g_object_storage_store_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, off64_t *pos)
{
bool result; /* Bilan à retourner */
- packed_buffer_t pbuf; /* Tampon des données à écrire */
storage_backend_t *backend; /* Informations à consulter */
off64_t tmp; /* Conservation éphémère */
- /* Phase de conversion */
-
- init_packed_buffer(&pbuf);
-
- result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), &pbuf);
- if (!result) goto exit;
-
- result = g_serializable_object_store(object, storage, &pbuf);
- if (!result) goto exit;
-
- /* Enregistrement */
-
result = false;
g_mutex_lock(&storage->mutex);
@@ -814,54 +1130,18 @@ bool g_object_storage_store_object(GObjectStorage *storage, const char *name, co
*pos = lseek64(backend->fd, 0, SEEK_CUR);
if (*pos != (off64_t)-1)
- result = write_packed_buffer(&pbuf, backend->fd);
-
- }
-
- g_mutex_unlock(&storage->mutex);
-
- /* Sortie propre */
-
- exit:
-
- exit_packed_buffer(&pbuf);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : storage = gestionnaire à manipuler. *
-* name = désignation d'un nouveau groupe d'objets. *
-* pbuf = zone tampon à remplir. *
-* *
-* Description : Sauvegarde un object interne sous forme de données. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_object_storage_pack_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, packed_buffer_t *pbuf)
-{
- bool result; /* Bilan à retourner */
- off64_t pos; /* Localisation des données */
-
- if (object == NULL)
- result = extend_packed_buffer(pbuf, (uint64_t []){ 0 }, sizeof(uint64_t), true);
+ {
+ result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), backend->fd);
- else
- {
- result = g_object_storage_store_object(storage, name, object, &pos);
+ if (result)
+ result = g_serializable_object_store(object, storage, backend->fd);
- if (result)
- result = extend_packed_buffer(pbuf, (uint64_t []){ pos }, sizeof(uint64_t), true);
+ }
}
+ g_mutex_unlock(&storage->mutex);
+
return result;
}
diff --git a/src/analysis/storage/storage.h b/src/glibext/storage.h
index cc0caad..ea06ed4 100644
--- a/src/analysis/storage/storage.h
+++ b/src/glibext/storage.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* storage.h - prototypes pour la conservation sur disque d'objets construits
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,69 +21,61 @@
*/
-#ifndef _ANALYSIS_STORAGE_STORAGE_H
-#define _ANALYSIS_STORAGE_STORAGE_H
+#ifndef _GLIBEXT_STORAGE_H
+#define _GLIBEXT_STORAGE_H
-#include <glib-object.h>
-#include <stdbool.h>
+#include <stdint.h>
+#include "helpers.h"
#include "serialize.h"
-#include "tpmem.h"
-#define G_TYPE_OBJECT_STORAGE g_object_storage_get_type()
-#define G_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_OBJECT_STORAGE, GObjectStorage))
-#define G_IS_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_OBJECT_STORAGE))
-#define G_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_OBJECT_STORAGE, GObjectStorageClass))
-#define G_IS_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_OBJECT_STORAGE))
-#define G_OBJECT_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_OBJECT_STORAGE, GObjectStorageClass))
+#define G_TYPE_OBJECT_STORAGE (g_object_storage_get_type())
+DECLARE_GTYPE(GObjectStorage, g_object_storage, G, OBJECT_STORAGE);
-/* Définition d'une conservation d'objets construits (instance) */
-typedef struct _GObjectStorage GObjectStorage;
-
-/* Définition d'une conservation d'objets construits (classe) */
-typedef struct _GObjectStorageClass GObjectStorageClass;
-
-
-/* Indique le type défini pour une conservation d'objets construits. */
-GType g_object_storage_get_type(void);
/* Crée le support d'une conservation d'objets en place. */
-GObjectStorage *g_object_storage_new(const char *);
-
-#define get_storage_linked_format(s) \
- ({ \
- void*__result; \
- __result = g_object_get_data(G_OBJECT(s), "format"); \
- g_object_ref(G_OBJECT(__result)); \
- __result; \
- })
+GObjectStorage *g_object_storage_new(const char *, uint8_t, const char *);
/* Charge le support d'une conservation d'objets en place. */
-GObjectStorage *g_object_storage_load(packed_buffer_t *);
+GObjectStorage *g_object_storage_load(const char *);
/* Sauvegarde le support d'une conservation d'objets en place. */
-bool g_object_storage_store(GObjectStorage *, packed_buffer_t *);
+bool g_object_storage_store(GObjectStorage *, const char *);
/* Charge un objet à partir de données rassemblées. */
GSerializableObject *g_object_storage_load_object(GObjectStorage *, const char *, off64_t);
-/* Charge un objet interne à partir de données rassemblées. */
-GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, const char *, packed_buffer_t *);
+/* Charge un objet interne à partir d'une référence embarquée. */
+GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, int, const char *);
/* Sauvegarde un object sous forme de données rassemblées. */
bool g_object_storage_store_object(GObjectStorage *, const char *, const GSerializableObject *, off64_t *);
-/* Charge un objet interne à partir de données rassemblées. */
-bool g_object_storage_unpack_object_2(GObjectStorage *, const char *, packed_buffer_t *, GType, ...);
-/* Sauvegarde un object interne sous forme de données. */
-bool g_object_storage_pack_object(GObjectStorage *, const char *, const GSerializableObject *, packed_buffer_t *);
+
+
+#if 0
+
+/**
+ * TODO : REMME ?
+ */
+
+#define get_storage_linked_format(s) \
+ ({ \
+ void*__result; \
+ __result = g_object_get_data(G_OBJECT(s), "format"); \
+ g_object_ref(G_OBJECT(__result)); \
+ __result; \
+ })
+
+#endif
+
-#endif /* _ANALYSIS_STORAGE_STORAGE_H */
+#endif /* _GLIBEXT_STORAGE_H */
diff --git a/src/glibext/strbuilder-int.h b/src/glibext/strbuilder-int.h
new file mode 100644
index 0000000..d74e65c
--- /dev/null
+++ b/src/glibext/strbuilder-int.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strbuilder-int.h - définitions internes propres aux éléments exportant une chaîne de caractères
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_STRBUILDER_INT_H
+#define _GLIBEXT_STRBUILDER_INT_H
+
+
+#include "strbuilder.h"
+
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+typedef bool (* strbuilder_to_string_fc) (const GStringBuilder *, unsigned int, sized_binary_t *);
+
+
+/* Instance d'objet visant à être unique (interface) */
+struct _GStringBuilderInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ strbuilder_to_string_fc to_string; /* Conversion en chaîne */
+
+};
+
+
+
+#endif /* _GLIBEXT_STRBUILDER_INT_H */
diff --git a/src/glibext/strbuilder.c b/src/glibext/strbuilder.c
new file mode 100644
index 0000000..e48674c
--- /dev/null
+++ b/src/glibext/strbuilder.c
@@ -0,0 +1,89 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strbuilder.c - exportation d'une chaîne de caractères depuis un élément
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "strbuilder.h"
+
+
+#include "strbuilder-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_string_builder_default_init(GStringBuilderInterface *);
+
+
+
+/* Détermine le type d'une interface pour la constitution d'objets uniques. */
+G_DEFINE_INTERFACE(GStringBuilder, g_string_builder, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_builder_default_init(GStringBuilderInterface *iface)
+{
+ iface->to_string = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : builder = objet dont l'instance est exportable. *
+* flags = éventuelles indications pour l'opération. *
+* out = chaîne de caractères mise en place. [OUT] *
+* *
+* Description : Exporte une chaîne de caractères à partir d'un objet. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après *
+* usage. *
+* *
+******************************************************************************/
+
+bool g_string_builder_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
+{
+ bool result; /* Bilan à retourner */
+ GStringBuilderInterface *iface; /* Interface utilisée */
+
+ iface = G_STRING_BUILDER_GET_IFACE(builder);
+
+ if (iface->to_string == NULL)
+ result = false;
+
+ else
+ result = iface->to_string(builder, flags, out);
+
+ return result;
+
+}
diff --git a/src/glibext/strbuilder.h b/src/glibext/strbuilder.h
new file mode 100644
index 0000000..b6422f7
--- /dev/null
+++ b/src/glibext/strbuilder.h
@@ -0,0 +1,46 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strbuilder.h - prototypes pour l'exportation d'une chaîne de caractères depuis un élément
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_STRBUILDER_H
+#define _GLIBEXT_STRBUILDER_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+#include "../common/szbin.h"
+
+
+
+#define G_TYPE_STRING_BUILDER (g_string_builder_get_type())
+
+DECLARE_INTERFACE(GStringBuilder, g_string_builder, G, STRING_BUILDER);
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+bool g_string_builder_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
+
+
+
+#endif /* _GLIBEXT_STRBUILDER_H */
diff --git a/src/glibext/tpmem-int.h b/src/glibext/tpmem-int.h
new file mode 100644
index 0000000..b1b7eec
--- /dev/null
+++ b/src/glibext/tpmem-int.h
@@ -0,0 +1,78 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tpmem-int.h - définitions internes propres à la mémorisation des types d'objets mis en cache
+ *
+ * Copyright (C) 2020-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_TPMEM_INT_H
+#define _GLIBEXT_TPMEM_INT_H
+
+
+#include "tpmem.h"
+
+
+/* Conservation d'une référence sur un type */
+typedef struct _gtype_ref_info_t
+{
+ GType gtype; /* Type pour la GLib */
+ gpointer gclass; /* Lien vers sa classe */
+
+ /**
+ * La GLib n'est pas très claire sur la taille de GType comme le montre le
+ * code issu de <sources>/gobject/gtype.h :
+ *
+ * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus
+ * typedef gsize GType;
+ * #else // for historic reasons, C++ links against gulong GTypes
+ * typedef gulong GType;
+ * #endif
+ *
+ * Et :
+ *
+ * typedef unsigned $glib_size_type_define gsize;
+ *
+ * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits
+ * lors des enregistrements.
+ */
+
+} gtype_ref_info_t;
+
+
+/* Définition d'une mémoire de types d'objets (instance) */
+struct _GTypeMemory
+{
+ GObject parent; /* A laisser en premier */
+
+ gtype_ref_info_t *gtypes; /* Types des objets reconnus */
+ size_t count; /* Quantité de ces objets */
+ GMutex mutex; /* Contrôle d'accès à la liste */
+
+};
+
+/* Définition d'une mémoire de types d'objets (classe) */
+struct _GTypeMemoryClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GLIBEXT_TPMEM_INT_H */
diff --git a/src/analysis/storage/tpmem.c b/src/glibext/tpmem.c
index 0703aeb..14b5e33 100644
--- a/src/analysis/storage/tpmem.c
+++ b/src/glibext/tpmem.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* tpmem.c - mémorisation des types d'objets mis en cache
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,59 +25,14 @@
#include <assert.h>
-#include <stdint.h>
-#include "../db/misc/rlestr.h"
-#include "../../arch/operands/target.h"
-#include "../../core/logs.h"
+#include "tpmem-int.h"
+#include "../common/szbin.h"
+#include "../core/logs.h"
-/* Conservation d'une référence sur un type */
-typedef struct _gtype_ref_info_t
-{
- GType gtype; /* Type pour la GLib */
- gpointer gclass; /* Lien vers sa classe */
-
- /**
- * La GLib n'est pas très claire sur la taille de GType :
- *
- * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus
- * typedef gsize GType;
- * #else // for historic reasons, C++ links against gulong GTypes
- * typedef gulong GType;
- * #endif
- *
- * Et :
- *
- * typedef unsigned $glib_size_type_define gsize;
- *
- * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits
- * lors des enregistrements.
- */
-
-} gtype_ref_info_t;
-
-/* Définition d'une mémoire de types d'objets (instance) */
-struct _GTypeMemory
-{
- GObject parent; /* A laisser en premier */
-
- gtype_ref_info_t *gtypes; /* Types des objets reconnus */
- size_t count; /* Quantité de ces objets */
- GMutex mutex; /* Contrôle d'accès à la liste */
-
-};
-
-/* Définition d'une mémoire de types d'objets (classe) */
-struct _GTypeMemoryClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
/* Initialise la classe des mémoires de types d'objets. */
static void g_type_memory_class_init(GTypeMemoryClass *);
@@ -85,10 +40,10 @@ static void g_type_memory_class_init(GTypeMemoryClass *);
static void g_type_memory_init(GTypeMemory *);
/* Supprime toutes les références externes. */
-static void g_type_memory_dispose(GTypeMemory *);
+static void g_type_memory_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_type_memory_finalize(GTypeMemory *);
+static void g_type_memory_finalize(GObject *);
@@ -114,8 +69,8 @@ static void g_type_memory_class_init(GTypeMemoryClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_type_memory_dispose;
- object->finalize = (GObjectFinalizeFunc)g_type_memory_finalize;
+ object->dispose = g_type_memory_dispose;
+ object->finalize = g_type_memory_finalize;
}
@@ -143,7 +98,7 @@ static void g_type_memory_init(GTypeMemory *tpmem)
/******************************************************************************
* *
-* Paramètres : tpmem = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -153,10 +108,13 @@ static void g_type_memory_init(GTypeMemory *tpmem)
* *
******************************************************************************/
-static void g_type_memory_dispose(GTypeMemory *tpmem)
+static void g_type_memory_dispose(GObject *object)
{
+ GTypeMemory *tpmem; /* Version spécialisée */
uint64_t i; /* Boucle de parcours */
+ tpmem = G_TYPE_MEMORY(object);
+
g_mutex_lock(&tpmem->mutex);
for (i = 0; i < tpmem->count; i++)
@@ -167,14 +125,14 @@ static void g_type_memory_dispose(GTypeMemory *tpmem)
g_mutex_clear(&tpmem->mutex);
- G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(G_OBJECT(tpmem));
+ G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : tpmem = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -184,12 +142,16 @@ static void g_type_memory_dispose(GTypeMemory *tpmem)
* *
******************************************************************************/
-static void g_type_memory_finalize(GTypeMemory *tpmem)
+static void g_type_memory_finalize(GObject *object)
{
+ GTypeMemory *tpmem; /* Version spécialisée */
+
+ tpmem = G_TYPE_MEMORY(object);
+
if (tpmem->gtypes != NULL)
free(tpmem->gtypes);
- G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(G_OBJECT(tpmem));
+ G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(object);
}
@@ -220,7 +182,7 @@ GTypeMemory *g_type_memory_new(void)
/******************************************************************************
* *
* Paramètres : tpmem = mémoire à compléter. *
-* pbuf = zone tampon à lire. *
+* fd = flux ouvert en lecture. *
* *
* Description : Apprend tous les types mémorisés dans un tampon. *
* *
@@ -230,14 +192,14 @@ GTypeMemory *g_type_memory_new(void)
* *
******************************************************************************/
-bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf)
+bool g_type_memory_load(GTypeMemory *tpmem, int fd)
{
bool result; /* Bilan à enregistrer */
uleb128_t count; /* Nombre d'éléments détectés */
uleb128_t i; /* Boucle de parcours */
- rle_string str; /* Chaîne à charger */
+ sized_binary_t str; /* Chaîne à charger */
- result = unpack_uleb128(&count, pbuf);
+ result = load_uleb128(&count, fd);
if (result)
{
@@ -248,35 +210,27 @@ bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf)
assert(tpmem->gtypes == NULL);
tpmem->gtypes = calloc(count, sizeof(gtype_ref_info_t));
- setup_empty_rle_string(&str);
-
for (i = 0; i < tpmem->count && result; i++)
{
- result = unpack_rle_string(&str, pbuf);
+ result = load_sized_binary_as_string(&str, fd);
if (!result) break;
- if (get_rle_string(&str) == NULL)
- {
- exit_rle_string(&str);
- break;
- }
-
- tpmem->gtypes[i].gtype = g_type_from_name(get_rle_string(&str));
+ tpmem->gtypes[i].gtype = g_type_from_name(str.data);
result = (tpmem->gtypes[i].gtype != 0);
if (!result)
- log_variadic_message(LMT_ERROR, "Unknown type: '%s'", get_rle_string(&str));
+ log_variadic_message(LMT_ERROR, "Unknown type: '%s'", str.data);
else
tpmem->gtypes[i].gclass = g_type_class_ref(tpmem->gtypes[i].gtype);
- exit_rle_string(&str);
+ exit_sized_binary(&str);
}
- }
+ g_mutex_unlock(&tpmem->mutex);
- g_mutex_unlock(&tpmem->mutex);
+ }
return result;
@@ -285,38 +239,40 @@ bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf)
/******************************************************************************
* *
-* Paramètres : tpmem = mémoire à manipuler. *
-* pbuf = zone tampon à venir lire. *
+* Paramètres : tpmem = mémoire à consulter. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Crée une nouvelle instance d'objet à partir de son type. *
+* Description : Enregistre tous les types mémorisés dans un tampon. *
* *
-* Retour : Instance issue de l'opération ou NULL. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf)
+bool g_type_memory_store(GTypeMemory *tpmem, int fd)
{
- GObject *result; /* Nouvelle instance à renvoyer*/
- uleb128_t index; /* Indice du point d'insertion */
- bool status; /* Bilan d'une récupération */
+ bool result; /* Bilan à enregistrer */
+ uint64_t i; /* Boucle de parcours */
+ const gchar *name; /* Désignation d'un type */
+ sized_binary_t str; /* Chaîne à conserver */
- result = NULL;
+ g_mutex_lock(&tpmem->mutex);
- status = unpack_uleb128(&index, pbuf);
+ result = store_uleb128((uleb128_t []){ tpmem->count }, fd);
- if (status)
+ for (i = 0; i < tpmem->count && result; i++)
{
- g_mutex_lock(&tpmem->mutex);
+ name = g_type_name(tpmem->gtypes[i].gtype);
- if (index < tpmem->count)
- result = g_object_new(tpmem->gtypes[index].gtype, NULL);
+ setup_sized_binary_from_static_string(&str, name);
- g_mutex_unlock(&tpmem->mutex);
+ store_sized_binary_as_string(&str, fd);
}
+ g_mutex_unlock(&tpmem->mutex);
+
return result;
}
@@ -325,60 +281,35 @@ GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf)
/******************************************************************************
* *
* Paramètres : tpmem = mémoire à manipuler. *
-* obj = instance dont le type est à mémoriser. *
-* pbuf = zone tampon à remplir. [OUT] *
+* fd = flux ouvert en lecture. *
* *
-* Description : Sauvegarde le type d'un objet instancié. *
+* Description : Crée une nouvelle instance d'objet à partir de son type. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Instance issue de l'opération ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_buffer_t *pbuf)
+GObject *g_type_memory_create_object_from_gtype(GTypeMemory *tpmem, int fd)
{
- bool result; /* Bilan à retourner */
- GType gtype; /* Type à enregistrer */
- size_t index; /* Indice du point d'insertion */
-
- gtype = G_TYPE_FROM_INSTANCE(obj);
+ GObject *result; /* Nouvelle instance à renvoyer*/
+ uleb128_t index; /* Indice du point d'insertion */
+ bool status; /* Bilan d'une récupération */
- /**
- * Pour quelques explications sur l'esquive suivante, se rapporter aux
- * commentaires de g_target_operand_unserialize().
- *
- * Dans la situation présente, on ne doit pas enregistrer le type dans le tampon,
- * car l'opérande va relancer l'opération entière (avec un opérande temporaire),
- * ce qui conduirait à l'enregistrement de deux types successifs dans les données.
- */
+ result = NULL;
- if (gtype == G_TYPE_TARGET_OPERAND)
- result = true;
+ status = load_uleb128(&index, fd);
- else
+ if (status)
{
g_mutex_lock(&tpmem->mutex);
- for (index = 0; index < tpmem->count; index++)
- if (tpmem->gtypes[index].gtype == gtype)
- break;
-
- if (index == tpmem->count)
- {
- tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t));
-
- assert(tpmem->count > 0);
-
- tpmem->gtypes[index].gtype = gtype;
- tpmem->gtypes[index].gclass = g_type_class_ref(gtype);
-
- }
+ if (index < tpmem->count)
+ result = g_object_new(tpmem->gtypes[index].gtype, NULL);
g_mutex_unlock(&tpmem->mutex);
- result = pack_uleb128((uleb128_t []){ index }, pbuf);
-
}
return result;
@@ -388,10 +319,11 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b
/******************************************************************************
* *
-* Paramètres : tpmem = mémoire à consulter. *
-* pbuf = zone tampon à remplir. [OUT] *
+* Paramètres : tpmem = mémoire à manipuler. *
+* obj = instance dont le type est à mémoriser. *
+* fd = flux ouvert en écriture. *
* *
-* Description : Enregistre tous les types mémorisés dans un tampon. *
+* Description : Sauvegarde le type d'un objet instancié. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -399,31 +331,33 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b
* *
******************************************************************************/
-bool g_type_memory_store_types(GTypeMemory *tpmem, packed_buffer_t *pbuf)
+bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, int fd)
{
- bool result; /* Bilan à enregistrer */
- uint64_t i; /* Boucle de parcours */
- const gchar *name; /* Désignation d'un type */
- rle_string str; /* Chaîne à conserver */
+ bool result; /* Bilan à retourner */
+ GType gtype; /* Type à enregistrer */
+ size_t index; /* Indice du point d'insertion */
+
+ gtype = G_TYPE_FROM_INSTANCE(obj);
g_mutex_lock(&tpmem->mutex);
- result = pack_uleb128((uleb128_t []){ tpmem->count }, pbuf);
+ for (index = 0; index < tpmem->count; index++)
+ if (tpmem->gtypes[index].gtype == gtype)
+ break;
- for (i = 0; i < tpmem->count && result; i++)
+ if (index == tpmem->count)
{
- name = g_type_name(tpmem->gtypes[i].gtype);
-
- init_static_rle_string(&str, name);
+ tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t));
- result = pack_rle_string(&str, pbuf);
-
- exit_rle_string(&str);
+ tpmem->gtypes[index].gtype = gtype;
+ tpmem->gtypes[index].gclass = g_type_class_ref(gtype);
}
g_mutex_unlock(&tpmem->mutex);
+ result = store_uleb128((uleb128_t []){ index }, fd);
+
return result;
}
diff --git a/src/glibext/tpmem.h b/src/glibext/tpmem.h
new file mode 100644
index 0000000..ccb8323
--- /dev/null
+++ b/src/glibext/tpmem.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tpmem.h - prototypes pour la mémorisation des types d'objets mis en cache
+ *
+ * Copyright (C) 2020-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_TPMEM_H
+#define _GLIBEXT_TPMEM_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_TYPE_MEMORY (g_type_memory_get_type())
+
+DECLARE_GTYPE(GTypeMemory, g_type_memory, G, TYPE_MEMORY);
+
+
+/* Crée une mémoire pour types d'objets. */
+GTypeMemory *g_type_memory_new(void);
+
+/* Apprend tous les types mémorisés dans un tampon. */
+bool g_type_memory_load(GTypeMemory *, int);
+
+/* Enregistre tous les types mémorisés dans un tampon. */
+bool g_type_memory_store(GTypeMemory *, int);
+
+/* Crée une nouvelle instance d'objet à partir de son type. */
+GObject *g_type_memory_create_object_from_gtype(GTypeMemory *, int);
+
+/* Sauvegarde le type d'un objet instancié. */
+bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, int);
+
+
+
+#endif /* _GLIBEXT_TPMEM_H */
diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c
index 7e06578..0a3dbe6 100644
--- a/src/glibext/widthtracker.c
+++ b/src/glibext/widthtracker.c
@@ -330,13 +330,17 @@ void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, in
void g_width_tracker_compute_width(const GWidthTracker *tracker, int *width)
{
+ size_t col_count; /* Nombre maximum de colonnes */
size_t i; /* Boucle de parcours */
*width = 0;
- // FIX access to col_count
- for (i = 0; i < tracker->col_count; i++)
+
+ col_count = tracker->opt_count + tracker->reg_count;
+
+
+ for (i = 0; i < col_count; i++)
*width += tracker->min_widths[i];
}
diff --git a/src/glibext/work-int.h b/src/glibext/work-int.h
index 4f84e86..58293e5 100644
--- a/src/glibext/work-int.h
+++ b/src/glibext/work-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed-int.h - définitions internes pour la gestion des travaux différés
+ * work-int.h - définitions internes pour la gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,27 +21,26 @@
*/
-#ifndef _GLIBEXT_DELAYED_INT_H
-#define _GLIBEXT_DELAYED_INT_H
+#ifndef _GLIBEXT_WORK_INT_H
+#define _GLIBEXT_WORK_INT_H
-#include "delayed.h"
+#include "work.h"
-#include "notifier.h"
-#include "../common/dllist.h"
+#include <stdbool.h>
+#include "../common/dllist.h"
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
/* Traite un travail programmé. */
-typedef void (* run_task_fc) (GDelayedWork *, GtkStatusStack *);
+typedef void (* run_work_fc) (GGenericWork *);
/* Travail différé (instance) */
-struct _GDelayedWork
+struct _GGenericWork
{
GObject parent; /* A laisser en premier */
@@ -54,22 +53,18 @@ struct _GDelayedWork
};
/* Travail différé (classe) */
-struct _GDelayedWorkClass
+struct _GGenericWorkClass
{
GObjectClass parent; /* A laisser en premier */
- run_task_fc run; /* Traitement externalisé */
+ run_work_fc run; /* Traitement externalisé */
/* Signaux */
- void (* work_completed) (GDelayedWork *);
+ void (* work_completed) (GGenericWork *);
};
-#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link)
-#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link)
-
-
-#endif /* _GLIBEXT_DELAYED_INT_H */
+#endif /* _GLIBEXT_WORK_INT_H */
diff --git a/src/glibext/work.c b/src/glibext/work.c
index 6b5ac35..218fcf8 100644
--- a/src/glibext/work.c
+++ b/src/glibext/work.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed.c - gestion des travaux différés
+ * work.c - gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,178 +21,29 @@
*/
-#include "delayed.h"
+#include "work.h"
-#include <assert.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <string.h>
+#include "work-int.h"
-#include "delayed-int.h"
-#include "../core/nproc.h"
-#ifdef INCLUDE_GTK_SUPPORT
-# include "../gui/core/global.h"
-#endif
-
-
-
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-
/* Initialise la classe des travaux différés. */
-static void g_delayed_work_class_init(GDelayedWorkClass *);
+static void g_generic_work_class_init(GGenericWorkClass *);
/* Initialise une instance de travail différé. */
-static void g_delayed_work_init(GDelayedWork *);
+static void g_generic_work_init(GGenericWork *);
/* Supprime toutes les références externes. */
-static void g_delayed_work_dispose(GDelayedWork *);
+static void g_generic_work_dispose(GGenericWork *);
/* Procède à la libération totale de la mémoire. */
-static void g_delayed_work_finalize(GDelayedWork *);
-
-/* Mène l'opération programmée. */
-static void g_delayed_work_process(GDelayedWork *, GtkStatusStack *);
-
-
-
-/* -------------------------- THREAD DE TRAITEMENTS DEDIES -------------------------- */
-
-
-#define G_TYPE_WORK_GROUP g_work_group_get_type()
-#define G_WORK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_work_group_get_type(), GWorkGroup))
-#define G_IS_WORK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_work_group_get_type()))
-#define G_WORK_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WORK_GROUP, GWorkGroupClass))
-#define G_IS_WORK_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WORK_GROUP))
-#define G_WORK_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WORK_GROUP, GWorkGroupClass))
-
-
-/* File de traitement pour un type donné (instance) */
-typedef struct _GWorkGroup
-{
- GObject parent; /* A laisser en premier */
-
- wgroup_id_t id; /* Identifiant de travaux menés*/
-
- GDelayedWork *works; /* Tâches à mener à bien */
- GMutex mutex; /* Verrou pour l'accès */
- GCond cond; /* Réveil pour un traitement */
- GCond wait_cond; /* Réveil d'attente de fin */
- gint pending; /* Tâches en cours d'exécution */
-
- GThread **threads; /* Procédure de traitement */
- guint threads_count; /* Nombre de procédures */
- bool force_exit; /* Procédure d'arrêt */
-
- wait_for_incoming_works_cb callback; /* Encadre les attentes de fin */
- void *data; /* Données à associer */
-
-} GWorkGroup;
-
-/* File de traitement pour un type donné (classe) */
-typedef struct _GWorkGroupClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-} GWorkGroupClass;
-
-
-/* Indique le type défini pour les groupes de travail. */
-static GType g_work_group_get_type(void);
-
-/* Initialise la classe des groupes de travail. */
-static void g_work_group_class_init(GWorkGroupClass *);
-
-/* Initialise une instance de groupe de travail. */
-static void g_work_group_init(GWorkGroup *);
-
-/* Supprime toutes les références externes. */
-static void g_work_group_dispose(GWorkGroup *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_work_group_finalize(GWorkGroup *);
-
-/* Crée un nouveau thread dédié à un type de travaux donné. */
-static GWorkGroup *g_work_group_new(wgroup_id_t, const guint *);
-
-/* Fournit l'identifiant associé à un groupe de travail. */
-static wgroup_id_t g_work_group_get_id(const GWorkGroup *);
-
-/* Place une nouvelle tâche en attente dans une file dédiée. */
-static void g_work_group_schedule(GWorkGroup *, GDelayedWork *);
-
-/* Assure le traitement en différé. */
-static void *g_work_group_process(GWorkGroup *);
-
-/* Détermine si le groupe est vide de toute programmation. */
-static bool g_work_group_is_empty(GWorkGroup *);
-
-/* Attend que toutes les tâches d'un groupe soient traitées. */
-static void g_work_group_wait_for_completion(GWorkGroup *, GWorkQueue *);
-
-/* Modifie les conditions d'attente des fins d'exécutions. */
-static void g_work_group_set_extra_wait_callback(GWorkGroup *, wait_for_incoming_works_cb, void *);
-
-/* Force un réveil d'une attente en cours pour la confirmer. */
-static void g_work_group_wake_up_waiters(GWorkGroup *);
-
-
+static void g_generic_work_finalize(GGenericWork *);
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
-
-/* Gestionnaire des travaux différés (instance) */
-struct _GWorkQueue
-{
- GObject parent; /* A laisser en premier */
-
- wgroup_id_t generator; /* Générateur d'identifiants */
-
- GWorkGroup **groups; /* Files de traitement */
- size_t groups_count; /* Nombre de files internes */
- GMutex mutex; /* Verrou pour l'accès */
- GCond wait_all; /* Réveil d'attente globale */
-
-};
-
-/* Gestionnaire des travaux différés (classe) */
-struct _GWorkQueueClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des travaux différés. */
-static void g_work_queue_class_init(GWorkQueueClass *);
-
-/* Initialise une instance de gestionnaire de travaux différés. */
-static void g_work_queue_init(GWorkQueue *);
-
-/* Supprime toutes les références externes. */
-static void g_work_queue_dispose(GWorkQueue *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_work_queue_finalize(GWorkQueue *);
-
-/* Donne l'assurance de l'existence d'un groupe de travail. */
-static bool g_work_queue_ensure_group_exists(GWorkQueue *, wgroup_id_t, const guint *);
-
-/* Fournit le groupe de travail correspondant à un identifiant. */
-static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *, wgroup_id_t);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TACHE DIFFEREE DANS LE TEMPS */
-/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour les travaux différés. */
-G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GGenericWork, g_generic_work, G_TYPE_OBJECT);
/******************************************************************************
@@ -207,19 +58,19 @@ G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT);
* *
******************************************************************************/
-static void g_delayed_work_class_init(GDelayedWorkClass *klass)
+static void g_generic_work_class_init(GGenericWorkClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_work_dispose;
- object->finalize = (GObjectFinalizeFunc)g_delayed_work_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_generic_work_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_generic_work_finalize;
g_signal_new("work-completed",
- G_TYPE_DELAYED_WORK,
+ G_TYPE_GENERIC_WORK,
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GDelayedWorkClass, work_completed),
+ G_STRUCT_OFFSET(GGenericWorkClass, work_completed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
@@ -239,8 +90,10 @@ static void g_delayed_work_class_init(GDelayedWorkClass *klass)
* *
******************************************************************************/
-static void g_delayed_work_init(GDelayedWork *work)
+static void g_generic_work_init(GGenericWork *work)
{
+ DL_LIST_ITEM_INIT(&work->link);
+
work->completed = false;
g_mutex_init(&work->mutex);
g_cond_init(&work->cond);
@@ -260,12 +113,12 @@ static void g_delayed_work_init(GDelayedWork *work)
* *
******************************************************************************/
-static void g_delayed_work_dispose(GDelayedWork *work)
+static void g_generic_work_dispose(GGenericWork *work)
{
g_mutex_clear(&work->mutex);
g_cond_clear(&work->cond);
- G_OBJECT_CLASS(g_delayed_work_parent_class)->dispose(G_OBJECT(work));
+ G_OBJECT_CLASS(g_generic_work_parent_class)->dispose(G_OBJECT(work));
}
@@ -282,281 +135,19 @@ static void g_delayed_work_dispose(GDelayedWork *work)
* *
******************************************************************************/
-static void g_delayed_work_finalize(GDelayedWork *work)
-{
- G_OBJECT_CLASS(g_delayed_work_parent_class)->finalize(G_OBJECT(work));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = travail à effectuer. *
-* status = barre de statut à tenir informée. *
-* *
-* Description : Mène l'opération programmée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_process(GDelayedWork *work, GtkStatusStack *status)
-{
- G_DELAYED_WORK_GET_CLASS(work)->run(work, status);
-
- g_mutex_lock(&work->mutex);
-
- work->completed = true;
-
- g_cond_signal(&work->cond);
- g_mutex_unlock(&work->mutex);
-
- g_signal_emit_by_name(work, "work-completed");
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = travail à surveiller. *
-* *
-* Description : Attend la fin de l'exécution d'une tâche donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_delayed_work_wait_for_completion(GDelayedWork *work)
-{
- g_mutex_lock(&work->mutex);
-
- while (!work->completed)
- g_cond_wait(&work->cond, &work->mutex);
-
- g_mutex_unlock(&work->mutex);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* THREADS DES TRAITEMENTS DEDIES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les groupes de travail. */
-G_DEFINE_TYPE(GWorkGroup, g_work_group, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des groupes de travail. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_class_init(GWorkGroupClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_work_group_dispose;
- object->finalize = (GObjectFinalizeFunc)g_work_group_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = instance à initialiser. *
-* *
-* Description : Initialise une instance de groupe de travail. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_init(GWorkGroup *group)
-{
- group->works = NULL;
-
- g_mutex_init(&group->mutex);
- g_cond_init(&group->cond);
- g_cond_init(&group->wait_cond);
-
- g_atomic_int_set(&group->pending, 0);
-
- group->threads = NULL;
- group->threads_count = 0;
- group->force_exit = false;
-
- group->callback = NULL;
- group->data = NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_dispose(GWorkGroup *group)
-{
- guint i; /* Boucle de parcours */
- GDelayedWork *work; /* Travail à oublier */
-
- group->force_exit = true;
-
- /**
- * Concernant la pose du verrou, se référer aux commentaires de la
- * fonction g_work_group_process().
- */
-
- g_mutex_lock(&group->mutex);
-
- g_cond_broadcast(&group->cond);
-
- g_mutex_unlock(&group->mutex);
-
- for (i = 0; i < group->threads_count; i++)
- g_thread_join(group->threads[i]);
-
- while (!dl_list_empty(group->works))
- {
- work = group->works;
- delayed_work_list_del(work, &group->works);
-
- g_object_unref(G_OBJECT(work));
-
- }
-
- g_mutex_clear(&group->mutex);
- g_cond_clear(&group->cond);
- g_cond_clear(&group->wait_cond);
-
- G_OBJECT_CLASS(g_work_group_parent_class)->dispose(G_OBJECT(group));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_finalize(GWorkGroup *group)
-{
- if (group->threads != NULL)
- free(group->threads);
-
- G_OBJECT_CLASS(g_work_group_parent_class)->finalize(G_OBJECT(group));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : id = identifiant accordé au nouveau groupe. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Crée un nouveau thread dédié à un type de travaux donné. *
-* *
-* Retour : Structure associée au thread mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GWorkGroup *g_work_group_new(wgroup_id_t id, const guint *count)
-{
- GWorkGroup *result; /* Traiteur à retourner */
- guint i; /* Boucle de parcours */
- char name[16]; /* Désignation humaine */
-
- result = g_object_new(G_TYPE_WORK_GROUP, NULL);
-
- result->id = id;
-
- result->threads_count = get_max_online_threads();
-
- if (count != NULL && *count < result->threads_count)
- result->threads_count = *count;
-
- result->threads = (GThread **)calloc(result->threads_count, sizeof(GThread *));
-
- for (i = 0; i < result->threads_count; i++)
- {
- snprintf(name, sizeof(name), "wgrp_%" PRIu64 "-%u", id, i);
-
- result->threads[i] = g_thread_new(name, (GThreadFunc)g_work_group_process, result);
- if (!result->threads[i])
- goto start_error;
-
- }
-
- start_error:
-
- result->threads_count = i;
-
- assert(i > 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = gestionnaire des actions à mener. *
-* *
-* Description : Fournit l'identifiant associé à un groupe de travail. *
-* *
-* Retour : Identifiant unique attribué au groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static wgroup_id_t g_work_group_get_id(const GWorkGroup *group)
+static void g_generic_work_finalize(GGenericWork *work)
{
- return group->id;
+ G_OBJECT_CLASS(g_generic_work_parent_class)->finalize(G_OBJECT(work));
}
/******************************************************************************
* *
-* Paramètres : group = gestionnaire des actions à mener. *
-* work = nouvelle tâche à programmer, puis effectuer. *
+* Paramètres : work = travail à traiter. *
+* list = ensemble de travaux à considérer. [OUT] *
* *
-* Description : Place une nouvelle tâche en attente dans une file dédiée. *
+* Description : Intègre un travail dans une liste de tâches à effectuer. *
* *
* Retour : - *
* *
@@ -564,161 +155,19 @@ static wgroup_id_t g_work_group_get_id(const GWorkGroup *group)
* *
******************************************************************************/
-static void g_work_group_schedule(GWorkGroup *group, GDelayedWork *work)
+void g_generic_work_add_to_list(GGenericWork *work, GGenericWork **list)
{
- g_mutex_lock(&group->mutex);
-
- g_atomic_int_inc(&group->pending);
-
- delayed_work_list_add_tail(work, &group->works);
-
- g_cond_signal(&group->cond);
-
- g_mutex_unlock(&group->mutex);
+ dl_list_add_tail(work, list, GGenericWork, link);
}
/******************************************************************************
* *
-* Paramètres : group = gestionnaire des actions à mener. *
-* *
-* Description : Assure le traitement en différé. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void *g_work_group_process(GWorkGroup *group)
-{
- GDelayedWork *work; /* Traitement à mener */
- GtkStatusStack *status; /* Zone d'info éventuelle */
-
- while (1)
- {
- g_mutex_lock(&group->mutex);
-
- while (dl_list_empty(group->works) && !group->force_exit)
- g_cond_wait(&group->cond, &group->mutex);
-
- if (group->force_exit)
- {
- g_mutex_unlock(&group->mutex);
- break;
- }
-
- work = group->works;
- delayed_work_list_del(work, &group->works);
-
- g_mutex_unlock(&group->mutex);
-
-#ifdef INCLUDE_GTK_SUPPORT
- status = get_global_status();
-#else
- status = NULL;
-#endif
- g_delayed_work_process(work, status);
-
- g_object_unref(G_OBJECT(work));
-
- /**
- * Verrou ou pas verrou ?
- *
- * La documentation de la GLib indique que ce n'est pas nécessaire :
- *
- * '''
- * It is good practice to lock the same mutex as the waiting threads
- * while calling this function, though not required.
- * '''
- *
- * Ce conseil se trouve verbatim à l'adresse :
- *
- * https://developer.gnome.org/glib/stable/glib-Threads.html#g-cond-broadcast
- *
- * Dans la pratique, il peut arriver que l'attente de la fonction
- * g_work_group_wait_for_completion() ne soit jamais interrompue.
- *
- * La documentation POSIX est un peu plus orientée :
- *
- * '''
- * The pthread_cond_broadcast() functions may be called by a thread
- * whether or not it currently owns the mutex that threads calling
- * pthread_cond_wait() have associated with the condition variable
- * during their waits; however, if predictable scheduling behavior is
- * required, then that mutex shall be locked by the thread calling
- * pthread_cond_broadcast().
- * '''
- *
- * Ce passage complet est consultable à l'adresse :
- *
- * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_broadcast.html
- *
- * La page de manuel pthread_cond_broadcast(3) est quant à elle plus
- * directrice : aucun complément d'information sur le sujet n'est fourni
- * et les exemples associés utilisent implicement un verrou pendant
- * sont appel.
- */
-
- g_mutex_lock(&group->mutex);
-
- if (g_atomic_int_dec_and_test(&group->pending))
- g_cond_broadcast(&group->wait_cond);
-
- g_mutex_unlock(&group->mutex);
-
- }
-
- return NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = gestionnaire des actions à consulter. *
-* *
-* Description : Détermine si le groupe est vide de toute programmation. *
+* Paramètres : work = travail à traiter. *
+* list = ensemble de travaux à considérer. [OUT] *
* *
-* Retour : Etat du groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_work_group_is_empty(GWorkGroup *group)
-{
- bool result; /* Etat à retourner */
-
- /**
- * Pour que le résultat soit exploitable, il ne doit pas varier
- * en dehors de la zone couverte par le verrou du groupe avant
- * son utilisation par l'appelant.
- *
- * Il doit donc logiquement y avoir un autre verrou en amont et,
- * comme à priori on ne devrait pas bloquer les groupes principaux
- * pour un traitement particulier, cette procédure ne devrait concerner
- * que des groupes dynamiques.
- */
-
- g_mutex_lock(&group->mutex);
-
- result = dl_list_empty(group->works);
-
- g_mutex_unlock(&group->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = groupe dont les conclusions sont attendues. *
-* queue = queue d'appartenance pour les appels externes. *
-* *
-* Description : Attend que toutes les tâches d'un groupe soient traitées. *
+* Description : Supprime un travail d'une liste de tâches à effectuer. *
* *
* Retour : - *
* *
@@ -726,530 +175,18 @@ static bool g_work_group_is_empty(GWorkGroup *group)
* *
******************************************************************************/
-static void g_work_group_wait_for_completion(GWorkGroup *group, GWorkQueue *queue)
+void g_generic_work_remove_from_list(GGenericWork *work, GGenericWork **list)
{
- wait_for_incoming_works_cb callback; /* Procédure complémentaire */
-
- bool no_extra_check(GWorkQueue *_q, wgroup_id_t _id, void *_data)
- {
- return false;
- }
-
- callback = group->callback != NULL ? group->callback : no_extra_check;
-
- g_mutex_lock(&group->mutex);
-
- /**
- * On attend que :
- * - la liste des tâches programmées soit vide.
- * - il n'existe plus de tâche en cours.
- * - rien n'indique que de nouvelles tâches supplémentaires vont arriver.
- */
-
- while ((g_atomic_int_get(&group->pending) > 0 || callback(queue, group->id, group->data))
- && !group->force_exit)
- {
- g_cond_wait(&group->wait_cond, &group->mutex);
- }
-
- g_mutex_unlock(&group->mutex);
+ dl_list_del(work, list, GGenericWork, link);
}
/******************************************************************************
* *
-* Paramètres : group = groupe dont les paramètres sont à modifier. *
-* callback = éventuelle fonction à appeler ou NULL. *
-* data = données devant accompagner l'appel. *
-* *
-* Description : Modifie les conditions d'attente des fins d'exécutions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_set_extra_wait_callback(GWorkGroup *group, wait_for_incoming_works_cb callback, void *data)
-{
- group->callback = callback;
- group->data = data;
-
-}
-
-
-/******************************************************************************
+* Paramètres : work = travail à effectuer. *
* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Force un réveil d'une attente en cours pour la confirmer. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_wake_up_waiters(GWorkGroup *group)
-{
- /**
- * Concernant la pose du verrou, se référer aux commentaires de la
- * fonction g_work_group_process().
- */
-
- g_mutex_lock(&group->mutex);
-
- g_cond_broadcast(&group->wait_cond);
-
- g_mutex_unlock(&group->mutex);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRAITEMENT DE TACHES DIFFEREES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour le gestionnaire des travaux différés. */
-G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des travaux différés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_class_init(GWorkQueueClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_work_queue_dispose;
- object->finalize = (GObjectFinalizeFunc)g_work_queue_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance à initialiser. *
-* *
-* Description : Initialise une instance de gestionnaire de travaux différés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_init(GWorkQueue *queue)
-{
- queue->generator = 0;
-
- queue->groups = NULL;
- queue->groups_count = 0;
- g_mutex_init(&queue->mutex);
- g_cond_init(&queue->wait_all);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_dispose(GWorkQueue *queue)
-{
- size_t i; /* Boucle de parcours */
-
- g_mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->groups_count; i++)
- g_clear_object(&queue->groups[i]);
-
- g_mutex_unlock(&queue->mutex);
-
- g_mutex_clear(&queue->mutex);
- g_cond_clear(&queue->wait_all);
-
- G_OBJECT_CLASS(g_work_queue_parent_class)->dispose(G_OBJECT(queue));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_finalize(GWorkQueue *queue)
-{
- if (queue->groups != NULL)
- free(queue->groups);
-
- G_OBJECT_CLASS(g_work_queue_parent_class)->finalize(G_OBJECT(queue));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Créé un nouveau gestionnaire de tâches parallèles. *
-* *
-* Retour : Gestionnaire de traitements mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GWorkQueue *g_work_queue_new(void)
-{
- GWorkQueue *result; /* Instance à retourner */
-
- result = g_object_new(G_TYPE_WORK_QUEUE, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Donne l'assurance de l'existence d'un groupe de travail. *
-* *
-* Retour : true si un nouveau groupe a été constitué, false sinon. *
-* *
-* Remarques : Le verrou d'accès doit être posé par l'appelant. *
-* *
-******************************************************************************/
-
-static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id, const guint *count)
-{
- bool found; /* Bilan des recherches */
- size_t i; /* Boucle de parcours */
- GWorkGroup *group; /* Groupe à consulter */
-
- assert(!g_mutex_trylock(&queue->mutex));
-
- found = false;
-
- for (i = 0; i < queue->groups_count && !found; i++)
- {
- group = queue->groups[i];
- found = (g_work_group_get_id(group) == id);
- }
-
- if (!found)
- {
- queue->groups_count++;
- queue->groups = (GWorkGroup **)realloc(queue->groups,
- queue->groups_count * sizeof(GWorkGroup *));
-
- group = g_work_group_new(id, count);
- queue->groups[queue->groups_count - 1] = group;
-
- }
-
- return !found;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* *
-* Description : Constitue un nouveau groupe de travail. *
-* *
-* Retour : Nouvel identifiant unique d'un nouveau groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-wgroup_id_t g_work_queue_define_work_group(GWorkQueue *queue)
-{
- wgroup_id_t result; /* Valeur à retourner */
- bool created; /* Bilan d'une tentative */
-
- g_mutex_lock(&queue->mutex);
-
- do
- {
- result = queue->generator++;
- created = g_work_queue_ensure_group_exists(queue, result, NULL);
- }
- while (!created);
-
- g_mutex_unlock(&queue->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Constitue un nouveau petit groupe de travail. *
-* *
-* Retour : Nouvel identifiant unique d'un nouveau groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *queue, guint count)
-{
- wgroup_id_t result; /* Valeur à retourner */
- bool created; /* Bilan d'une tentative */
-
- g_mutex_lock(&queue->mutex);
-
- do
- {
- result = queue->generator++;
- created = g_work_queue_ensure_group_exists(queue, result, &count);
- }
- while (!created);
-
- g_mutex_unlock(&queue->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Dissout un groupe de travail existant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
-{
- size_t i; /* Boucle de parcours */
- GWorkGroup *group; /* Groupe de travail manipulé */
-#ifndef NDEBUG
- bool found; /* Repérage du groupe visé */
-#endif
-
-#ifndef NDEBUG
- found = false;
-#endif
-
- g_mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->groups_count; i++)
- {
- group = queue->groups[i];
-
- if (g_work_group_get_id(group) == id)
- {
- g_object_unref(G_OBJECT(group));
-
- memmove(&queue->groups[i], &queue->groups[i + 1],
- (queue->groups_count - i - 1) * sizeof(GWorkGroup *));
-
- queue->groups_count--;
- queue->groups = (GWorkGroup **)realloc(queue->groups,
- queue->groups_count * sizeof(GWorkGroup *));
-
-#ifndef NDEBUG
- found = true;
-#endif
-
- break;
-
- }
-
- }
-
- assert(found);
-
- g_cond_broadcast(&queue->wait_all);
-
- g_mutex_unlock(&queue->mutex);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire des actions à mener. *
-* work = nouvelle tâche à programmer, puis effectuer. *
-* id = identifiant du groupe de travail d'affectation. *
-* *
-* Description : Place une nouvelle tâche en attente. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work, wgroup_id_t id)
-{
- GWorkGroup *group; /* Groupe de travail à attendre*/
-
- group = g_work_queue_find_group_for_id(queue, id);
- assert(group != NULL);
-
- g_work_group_schedule(group, work);
-
- g_object_unref(G_OBJECT(group));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Fournit le groupe de travail correspondant à un identifiant. *
-* *
-* Retour : Eventuel groupe existant trouvé ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *queue, wgroup_id_t id)
-{
- GWorkGroup *result; /* Trouvaille à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- g_mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->groups_count; i++)
- if (g_work_group_get_id(queue->groups[i]) == id)
- {
- result = queue->groups[i];
- g_object_ref(G_OBJECT(result));
- break;
- }
-
- g_mutex_unlock(&queue->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Détermine si un groupe est vide de toute programmation. *
-* *
-* Retour : Etat du groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_work_queue_is_empty(GWorkQueue *queue, wgroup_id_t id)
-{
- bool result; /* Etat à retourner */
- GWorkGroup *group; /* Groupe de travail à attendre*/
-
- group = g_work_queue_find_group_for_id(queue, id);
-
- if (group != NULL)
- {
- result = g_work_group_is_empty(group);
- g_object_unref(G_OBJECT(group));
- }
-
- else
- result = true;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Attend que toutes les tâches d'un groupe soient traitées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
-{
- GWorkGroup *group; /* Groupe de travail à attendre*/
-
- group = g_work_queue_find_group_for_id(queue, id);
-
- if (group != NULL)
- {
- g_work_group_wait_for_completion(group, queue);
- g_object_unref(G_OBJECT(group));
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* gb_ids = identifiants de groupes globaux. *
-* gb_count = nombre de ces groupes globaux. *
-* *
-* Description : Attend que toutes les tâches de tout groupe soient traitées. *
+* Description : Mène l'opération programmée. *
* *
* Retour : - *
* *
@@ -1257,80 +194,27 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
* *
******************************************************************************/
-void g_work_queue_wait_for_all_completions(GWorkQueue *queue, const wgroup_id_t *gb_ids, size_t gb_count)
+void g_generic_work_process(GGenericWork *work)
{
- size_t i; /* Boucle de parcours */
-
- g_mutex_lock(&queue->mutex);
-
- wait_again:
-
- /**
- * Attente d'éventuels groupes isolés.
- */
-
- while (queue->groups_count > gb_count)
- g_cond_wait(&queue->wait_all, &queue->mutex);
-
- g_mutex_unlock(&queue->mutex);
-
- /**
- * Attente des groupes principaux.
- */
-
- for (i = 0; i < gb_count; i++)
- g_work_queue_wait_for_completion(queue, gb_ids[i]);
+ G_GENERIC_WORK_GET_CLASS(work)->run(work);
- /**
- * Si le groupe par défaut a généré de nouveaux groupes, on recommence !
- */
-
- g_mutex_lock(&queue->mutex);
-
- if (queue->groups_count > gb_count)
- goto wait_again;
-
- g_mutex_unlock(&queue->mutex);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
-* callback = éventuelle fonction à appeler ou NULL. *
-* data = données devant accompagner l'appel. *
-* *
-* Description : Modifie les conditions d'attente des fins d'exécutions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ g_mutex_lock(&work->mutex);
-void g_work_queue_set_extra_wait_callback(GWorkQueue *queue, wgroup_id_t id, wait_for_incoming_works_cb callback, void *data)
-{
- GWorkGroup *group; /* Groupe de travail à traiter */
+ work->completed = true;
- group = g_work_queue_find_group_for_id(queue, id);
+ g_cond_signal(&work->cond);
+ g_mutex_unlock(&work->mutex);
- if (group != NULL)
- {
- g_work_group_set_extra_wait_callback(group, callback, data);
- g_object_unref(G_OBJECT(group));
- }
+ g_signal_emit_by_name(work, "work-completed");
}
/******************************************************************************
* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
+* Paramètres : work = travail à surveiller. *
* *
-* Description : Force un réveil d'une attente en cours pour la confirmer. *
+* Description : Attend la fin de l'exécution d'une tâche donnée. *
* *
* Retour : - *
* *
@@ -1338,16 +222,13 @@ void g_work_queue_set_extra_wait_callback(GWorkQueue *queue, wgroup_id_t id, wai
* *
******************************************************************************/
-void g_work_queue_wake_up_waiters(GWorkQueue *queue, wgroup_id_t id)
+void g_generic_work_wait_for_completion(GGenericWork *work)
{
- GWorkGroup *group; /* Groupe de travail à traiter */
+ g_mutex_lock(&work->mutex);
- group = g_work_queue_find_group_for_id(queue, id);
+ while (!work->completed)
+ g_cond_wait(&work->cond, &work->mutex);
- if (group != NULL)
- {
- g_work_group_wake_up_waiters(group);
- g_object_unref(G_OBJECT(group));
- }
+ g_mutex_unlock(&work->mutex);
}
diff --git a/src/glibext/work.h b/src/glibext/work.h
index 89eed12..1084942 100644
--- a/src/glibext/work.h
+++ b/src/glibext/work.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed.h - prototypes pour la gestion des travaux différés
+ * work.h - prototypes pour la gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,107 +21,31 @@
*/
-#ifndef _GLIBEXT_DELAYED_H
-#define _GLIBEXT_DELAYED_H
+#ifndef _GLIBEXT_WORK_H
+#define _GLIBEXT_WORK_H
-#include <glib-object.h>
-#include <stdbool.h>
-#include <stdint.h>
+#include "helpers.h"
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
+#define G_TYPE_GENERIC_WORK (g_generic_work_get_type())
+DECLARE_GTYPE(GGenericWork, g_generic_work, G, GENERIC_WORK);
-#define G_TYPE_DELAYED_WORK g_delayed_work_get_type()
-#define G_DELAYED_WORK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_work_get_type(), GDelayedWork))
-#define G_IS_DELAYED_WORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_work_get_type()))
-#define G_DELAYED_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_WORK, GDelayedWorkClass))
-#define G_IS_DELAYED_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_WORK))
-#define G_DELAYED_WORK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_WORK, GDelayedWorkClass))
+/* Intègre un travail dans une liste de tâches à effectuer. */
+void g_generic_work_add_to_list(GGenericWork *, GGenericWork **);
-/* Travail différé (instance) */
-typedef struct _GDelayedWork GDelayedWork;
+/* Supprime un travail d'une liste de tâches à effectuer. */
+void g_generic_work_remove_from_list(GGenericWork *, GGenericWork **);
-/* Travail différé (classe) */
-typedef struct _GDelayedWorkClass GDelayedWorkClass;
-
-
-/* Indique le type défini pour les travaux différés. */
-GType g_delayed_work_get_type(void);
+/* Mène l'opération programmée. */
+void g_generic_work_process(GGenericWork *);
/* Attend la fin de l'exécution d'une tâche donnée. */
-void g_delayed_work_wait_for_completion(GDelayedWork *);
-
-
-
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
-
-#define G_TYPE_WORK_QUEUE g_work_queue_get_type()
-#define G_WORK_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_work_queue_get_type(), GWorkQueue))
-#define G_IS_WORK_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_work_queue_get_type()))
-#define G_WORK_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WORK_QUEUE, GWorkQueueClass))
-#define G_IS_WORK_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WORK_QUEUE))
-#define G_WORK_QUEUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WORK_QUEUE, GWorkQueueClass))
-
-
-/* Gestionnaire des travaux différés (instance) */
-typedef struct _GWorkQueue GWorkQueue;
-
-/* Gestionnaire des travaux différés (classe) */
-typedef struct _GWorkQueueClass GWorkQueueClass;
-
-
-/**
- * Identifiant unique pour groupe de travail.
- *
- * Le nombre de bits est forcé à 64 bits car glib-genmarshal ne reconnait
- * pas explicitement le type 'unsigned long long'.
- */
-typedef uint64_t wgroup_id_t;
-
-
-/* Indique le type défini pour le gestionnaire des travaux différés. */
-GType g_work_queue_get_type(void);
-
-/* Créé un nouveau gestionnaire de tâches parallèles. */
-GWorkQueue *g_work_queue_new(void);
-
-/* Constitue un nouveau groupe de travail. */
-wgroup_id_t g_work_queue_define_work_group(GWorkQueue *);
-
-/* Constitue un nouveau petit groupe de travail. */
-wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *, guint);
-
-/* Dissout un groupe de travail existant. */
-void g_work_queue_delete_work_group(GWorkQueue *, wgroup_id_t);
-
-/* Place une nouvelle tâche en attente. */
-void g_work_queue_schedule_work(GWorkQueue *, GDelayedWork *, wgroup_id_t);
-
-/* Détermine si un groupe est vide de toute programmation. */
-bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
-
-/* Attend que toutes les tâches d'un groupe soient traitées. */
-void g_work_queue_wait_for_completion(GWorkQueue *, wgroup_id_t);
-
-/* Attend que toutes les tâches de tout groupe soient traitées. */
-void g_work_queue_wait_for_all_completions(GWorkQueue *, const wgroup_id_t *, size_t);
-
-
-/* Etudie le besoin d'attendre d'avantage de prochaines tâches. */
-typedef bool (* wait_for_incoming_works_cb) (GWorkQueue *, wgroup_id_t, void *);
-
-
-/* Modifie les conditions d'attente des fins d'exécutions. */
-void g_work_queue_set_extra_wait_callback(GWorkQueue *, wgroup_id_t, wait_for_incoming_works_cb, void *);
-
-/* Force un réveil d'une attente en cours pour la confirmer. */
-void g_work_queue_wake_up_waiters(GWorkQueue *, wgroup_id_t);
+void g_generic_work_wait_for_completion(GGenericWork *);
-#endif /* _GLIBEXT_DELAYED_H */
+#endif /* _GLIBEXT_WORK_H */
diff --git a/src/glibext/workgroup-int.h b/src/glibext/workgroup-int.h
index 4f84e86..7224cf9 100644
--- a/src/glibext/workgroup-int.h
+++ b/src/glibext/workgroup-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed-int.h - définitions internes pour la gestion des travaux différés
+ * workgroup-int.h - définitions internes pour la gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,55 +21,40 @@
*/
-#ifndef _GLIBEXT_DELAYED_INT_H
-#define _GLIBEXT_DELAYED_INT_H
+#ifndef _GLIBEXT_WORKGROUP_INT_H
+#define _GLIBEXT_WORKGROUP_INT_H
-#include "delayed.h"
+#include "workgroup.h"
-#include "notifier.h"
-#include "../common/dllist.h"
-
-
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-
-
-/* Traite un travail programmé. */
-typedef void (* run_task_fc) (GDelayedWork *, GtkStatusStack *);
-
-
-/* Travail différé (instance) */
-struct _GDelayedWork
+/* File de traitement pour un type donné (instance) */
+typedef struct _GWorkGroup
{
GObject parent; /* A laisser en premier */
- DL_LIST_ITEM(link); /* Lien vers les maillons */
+ wgroup_id_t id; /* Identifiant de travaux menés*/
- bool completed; /* Fin de la tâche ? */
- GMutex mutex; /* Accès à la variable */
- GCond cond; /* Attente de changement */
+ GGenericWork *works; /* Tâches à mener à bien */
+ GMutex mutex; /* Verrou pour l'accès */
+ GCond cond; /* Réveil pour un traitement */
+ GCond wait_cond; /* Réveil d'attente de fin */
+ gint pending; /* Tâches en cours d'exécution */
-};
+ GThread **threads; /* Procédure de traitement */
+ guint threads_count; /* Nombre de procédures */
+ bool force_exit; /* Procédure d'arrêt */
-/* Travail différé (classe) */
-struct _GDelayedWorkClass
+} GWorkGroup;
+
+/* File de traitement pour un type donné (classe) */
+typedef struct _GWorkGroupClass
{
GObjectClass parent; /* A laisser en premier */
- run_task_fc run; /* Traitement externalisé */
-
- /* Signaux */
-
- void (* work_completed) (GDelayedWork *);
-
-};
-
-
-#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link)
-#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link)
+} GWorkGroupClass;
-#endif /* _GLIBEXT_DELAYED_INT_H */
+#endif /* _GLIBEXT_WORKGROUP_INT_H */
diff --git a/src/glibext/workgroup.c b/src/glibext/workgroup.c
index 6b5ac35..c603d54 100644
--- a/src/glibext/workgroup.c
+++ b/src/glibext/workgroup.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed.c - gestion des travaux différés
+ * workgroup.c - gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,88 +21,21 @@
*/
-#include "delayed.h"
+#include "workgroup.h"
#include <assert.h>
#include <inttypes.h>
#include <malloc.h>
#include <stdio.h>
-#include <string.h>
-#include "delayed-int.h"
+#include "workgroup-int.h"
+#include "../common/dllist.h"
#include "../core/nproc.h"
-#ifdef INCLUDE_GTK_SUPPORT
-# include "../gui/core/global.h"
-#endif
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-
-
-/* Initialise la classe des travaux différés. */
-static void g_delayed_work_class_init(GDelayedWorkClass *);
-
-/* Initialise une instance de travail différé. */
-static void g_delayed_work_init(GDelayedWork *);
-
-/* Supprime toutes les références externes. */
-static void g_delayed_work_dispose(GDelayedWork *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_delayed_work_finalize(GDelayedWork *);
-
-/* Mène l'opération programmée. */
-static void g_delayed_work_process(GDelayedWork *, GtkStatusStack *);
-
-
-
-/* -------------------------- THREAD DE TRAITEMENTS DEDIES -------------------------- */
-
-
-#define G_TYPE_WORK_GROUP g_work_group_get_type()
-#define G_WORK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_work_group_get_type(), GWorkGroup))
-#define G_IS_WORK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_work_group_get_type()))
-#define G_WORK_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WORK_GROUP, GWorkGroupClass))
-#define G_IS_WORK_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WORK_GROUP))
-#define G_WORK_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WORK_GROUP, GWorkGroupClass))
-
-
-/* File de traitement pour un type donné (instance) */
-typedef struct _GWorkGroup
-{
- GObject parent; /* A laisser en premier */
-
- wgroup_id_t id; /* Identifiant de travaux menés*/
-
- GDelayedWork *works; /* Tâches à mener à bien */
- GMutex mutex; /* Verrou pour l'accès */
- GCond cond; /* Réveil pour un traitement */
- GCond wait_cond; /* Réveil d'attente de fin */
- gint pending; /* Tâches en cours d'exécution */
-
- GThread **threads; /* Procédure de traitement */
- guint threads_count; /* Nombre de procédures */
- bool force_exit; /* Procédure d'arrêt */
-
- wait_for_incoming_works_cb callback; /* Encadre les attentes de fin */
- void *data; /* Données à associer */
-
-} GWorkGroup;
-
-/* File de traitement pour un type donné (classe) */
-typedef struct _GWorkGroupClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-} GWorkGroupClass;
-
-
-/* Indique le type défini pour les groupes de travail. */
-static GType g_work_group_get_type(void);
-
/* Initialise la classe des groupes de travail. */
static void g_work_group_class_init(GWorkGroupClass *);
@@ -115,237 +48,9 @@ static void g_work_group_dispose(GWorkGroup *);
/* Procède à la libération totale de la mémoire. */
static void g_work_group_finalize(GWorkGroup *);
-/* Crée un nouveau thread dédié à un type de travaux donné. */
-static GWorkGroup *g_work_group_new(wgroup_id_t, const guint *);
-
-/* Fournit l'identifiant associé à un groupe de travail. */
-static wgroup_id_t g_work_group_get_id(const GWorkGroup *);
-
-/* Place une nouvelle tâche en attente dans une file dédiée. */
-static void g_work_group_schedule(GWorkGroup *, GDelayedWork *);
-
/* Assure le traitement en différé. */
static void *g_work_group_process(GWorkGroup *);
-/* Détermine si le groupe est vide de toute programmation. */
-static bool g_work_group_is_empty(GWorkGroup *);
-
-/* Attend que toutes les tâches d'un groupe soient traitées. */
-static void g_work_group_wait_for_completion(GWorkGroup *, GWorkQueue *);
-
-/* Modifie les conditions d'attente des fins d'exécutions. */
-static void g_work_group_set_extra_wait_callback(GWorkGroup *, wait_for_incoming_works_cb, void *);
-
-/* Force un réveil d'une attente en cours pour la confirmer. */
-static void g_work_group_wake_up_waiters(GWorkGroup *);
-
-
-
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
-
-/* Gestionnaire des travaux différés (instance) */
-struct _GWorkQueue
-{
- GObject parent; /* A laisser en premier */
-
- wgroup_id_t generator; /* Générateur d'identifiants */
-
- GWorkGroup **groups; /* Files de traitement */
- size_t groups_count; /* Nombre de files internes */
- GMutex mutex; /* Verrou pour l'accès */
- GCond wait_all; /* Réveil d'attente globale */
-
-};
-
-/* Gestionnaire des travaux différés (classe) */
-struct _GWorkQueueClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des travaux différés. */
-static void g_work_queue_class_init(GWorkQueueClass *);
-
-/* Initialise une instance de gestionnaire de travaux différés. */
-static void g_work_queue_init(GWorkQueue *);
-
-/* Supprime toutes les références externes. */
-static void g_work_queue_dispose(GWorkQueue *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_work_queue_finalize(GWorkQueue *);
-
-/* Donne l'assurance de l'existence d'un groupe de travail. */
-static bool g_work_queue_ensure_group_exists(GWorkQueue *, wgroup_id_t, const guint *);
-
-/* Fournit le groupe de travail correspondant à un identifiant. */
-static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *, wgroup_id_t);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TACHE DIFFEREE DANS LE TEMPS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les travaux différés. */
-G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des travaux différés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_class_init(GDelayedWorkClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_work_dispose;
- object->finalize = (GObjectFinalizeFunc)g_delayed_work_finalize;
-
- g_signal_new("work-completed",
- G_TYPE_DELAYED_WORK,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GDelayedWorkClass, work_completed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = instance à initialiser. *
-* *
-* Description : Initialise une instance de travail différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_init(GDelayedWork *work)
-{
- work->completed = false;
- g_mutex_init(&work->mutex);
- g_cond_init(&work->cond);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_dispose(GDelayedWork *work)
-{
- g_mutex_clear(&work->mutex);
- g_cond_clear(&work->cond);
-
- G_OBJECT_CLASS(g_delayed_work_parent_class)->dispose(G_OBJECT(work));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_finalize(GDelayedWork *work)
-{
- G_OBJECT_CLASS(g_delayed_work_parent_class)->finalize(G_OBJECT(work));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = travail à effectuer. *
-* status = barre de statut à tenir informée. *
-* *
-* Description : Mène l'opération programmée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_process(GDelayedWork *work, GtkStatusStack *status)
-{
- G_DELAYED_WORK_GET_CLASS(work)->run(work, status);
-
- g_mutex_lock(&work->mutex);
-
- work->completed = true;
-
- g_cond_signal(&work->cond);
- g_mutex_unlock(&work->mutex);
-
- g_signal_emit_by_name(work, "work-completed");
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = travail à surveiller. *
-* *
-* Description : Attend la fin de l'exécution d'une tâche donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_delayed_work_wait_for_completion(GDelayedWork *work)
-{
- g_mutex_lock(&work->mutex);
-
- while (!work->completed)
- g_cond_wait(&work->cond, &work->mutex);
-
- g_mutex_unlock(&work->mutex);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* THREADS DES TRAITEMENTS DEDIES */
-/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour les groupes de travail. */
@@ -390,7 +95,7 @@ static void g_work_group_class_init(GWorkGroupClass *klass)
static void g_work_group_init(GWorkGroup *group)
{
- group->works = NULL;
+ DL_LIST_HEAD_INIT(group->works);
g_mutex_init(&group->mutex);
g_cond_init(&group->cond);
@@ -402,15 +107,12 @@ static void g_work_group_init(GWorkGroup *group)
group->threads_count = 0;
group->force_exit = false;
- group->callback = NULL;
- group->data = NULL;
-
}
/******************************************************************************
* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
+* Paramètres : group = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -423,7 +125,7 @@ static void g_work_group_init(GWorkGroup *group)
static void g_work_group_dispose(GWorkGroup *group)
{
guint i; /* Boucle de parcours */
- GDelayedWork *work; /* Travail à oublier */
+ GGenericWork *work; /* Travail à oublier */
group->force_exit = true;
@@ -444,9 +146,9 @@ static void g_work_group_dispose(GWorkGroup *group)
while (!dl_list_empty(group->works))
{
work = group->works;
- delayed_work_list_del(work, &group->works);
+ g_generic_work_remove_from_list(work, &group->works);
- g_object_unref(G_OBJECT(work));
+ unref_object(work);
}
@@ -484,7 +186,7 @@ static void g_work_group_finalize(GWorkGroup *group)
/******************************************************************************
* *
* Paramètres : id = identifiant accordé au nouveau groupe. *
-* count = quantité de threads à allouer. *
+* count = quantité de threads à allouer (0 pour un défaut). *
* *
* Description : Crée un nouveau thread dédié à un type de travaux donné. *
* *
@@ -494,33 +196,47 @@ static void g_work_group_finalize(GWorkGroup *group)
* *
******************************************************************************/
-static GWorkGroup *g_work_group_new(wgroup_id_t id, const guint *count)
+GWorkGroup *g_work_group_new(wgroup_id_t id, guint count)
{
- GWorkGroup *result; /* Traiteur à retourner */
+ GWorkGroup *result; /* Traiteur à retourner */
guint i; /* Boucle de parcours */
- char name[16]; /* Désignation humaine */
+ int ret; /* Bilan d'un appel */
+ char *name; /* Désignation humaine */
result = g_object_new(G_TYPE_WORK_GROUP, NULL);
result->id = id;
- result->threads_count = get_max_online_threads();
+ if (count == 0)
+ count = get_max_online_threads();
- if (count != NULL && *count < result->threads_count)
- result->threads_count = *count;
+ result->threads_count = count;
- result->threads = (GThread **)calloc(result->threads_count, sizeof(GThread *));
+ result->threads = calloc(result->threads_count, sizeof(GThread *));
for (i = 0; i < result->threads_count; i++)
{
- snprintf(name, sizeof(name), "wgrp_%" PRIu64 "-%u", id, i);
+ /**
+ * La documentation précise :
+ *
+ * Some systems restrict the length of name to 16 bytes.
+ *
+ * On laisse ces systèmes tronquer.
+ */
+
+ ret = asprintf(&name, "wgrp_%" PRIu64 "-%u", id, i);
+ if (ret == -1) goto naming_error;
result->threads[i] = g_thread_new(name, (GThreadFunc)g_work_group_process, result);
+
+ free(name);
+
if (!result->threads[i])
goto start_error;
}
+ naming_error:
start_error:
result->threads_count = i;
@@ -544,7 +260,7 @@ static GWorkGroup *g_work_group_new(wgroup_id_t id, const guint *count)
* *
******************************************************************************/
-static wgroup_id_t g_work_group_get_id(const GWorkGroup *group)
+wgroup_id_t g_work_group_get_id(const GWorkGroup *group)
{
return group->id;
@@ -564,13 +280,14 @@ static wgroup_id_t g_work_group_get_id(const GWorkGroup *group)
* *
******************************************************************************/
-static void g_work_group_schedule(GWorkGroup *group, GDelayedWork *work)
+void g_work_group_schedule(GWorkGroup *group, GGenericWork *work)
{
g_mutex_lock(&group->mutex);
g_atomic_int_inc(&group->pending);
- delayed_work_list_add_tail(work, &group->works);
+ ref_object(work);
+ g_generic_work_add_to_list(work, &group->works);
g_cond_signal(&group->cond);
@@ -593,8 +310,7 @@ static void g_work_group_schedule(GWorkGroup *group, GDelayedWork *work)
static void *g_work_group_process(GWorkGroup *group)
{
- GDelayedWork *work; /* Traitement à mener */
- GtkStatusStack *status; /* Zone d'info éventuelle */
+ GGenericWork *work; /* Traitement à mener */
while (1)
{
@@ -610,18 +326,13 @@ static void *g_work_group_process(GWorkGroup *group)
}
work = group->works;
- delayed_work_list_del(work, &group->works);
+ g_generic_work_remove_from_list(work, &group->works);
g_mutex_unlock(&group->mutex);
-#ifdef INCLUDE_GTK_SUPPORT
- status = get_global_status();
-#else
- status = NULL;
-#endif
- g_delayed_work_process(work, status);
+ g_generic_work_process(work);
- g_object_unref(G_OBJECT(work));
+ unref_object(work);
/**
* Verrou ou pas verrou ?
@@ -687,7 +398,7 @@ static void *g_work_group_process(GWorkGroup *group)
* *
******************************************************************************/
-static bool g_work_group_is_empty(GWorkGroup *group)
+bool g_work_group_is_empty(GWorkGroup *group)
{
bool result; /* Etat à retourner */
@@ -716,7 +427,6 @@ static bool g_work_group_is_empty(GWorkGroup *group)
/******************************************************************************
* *
* Paramètres : group = groupe dont les conclusions sont attendues. *
-* queue = queue d'appartenance pour les appels externes. *
* *
* Description : Attend que toutes les tâches d'un groupe soient traitées. *
* *
@@ -726,17 +436,8 @@ static bool g_work_group_is_empty(GWorkGroup *group)
* *
******************************************************************************/
-static void g_work_group_wait_for_completion(GWorkGroup *group, GWorkQueue *queue)
+void g_work_group_wait_for_completion(GWorkGroup *group)
{
- wait_for_incoming_works_cb callback; /* Procédure complémentaire */
-
- bool no_extra_check(GWorkQueue *_q, wgroup_id_t _id, void *_data)
- {
- return false;
- }
-
- callback = group->callback != NULL ? group->callback : no_extra_check;
-
g_mutex_lock(&group->mutex);
/**
@@ -746,7 +447,7 @@ static void g_work_group_wait_for_completion(GWorkGroup *group, GWorkQueue *queu
* - rien n'indique que de nouvelles tâches supplémentaires vont arriver.
*/
- while ((g_atomic_int_get(&group->pending) > 0 || callback(queue, group->id, group->data))
+ while ((g_atomic_int_get(&group->pending) > 0)
&& !group->force_exit)
{
g_cond_wait(&group->wait_cond, &group->mutex);
@@ -759,456 +460,43 @@ static void g_work_group_wait_for_completion(GWorkGroup *group, GWorkQueue *queu
/******************************************************************************
* *
-* Paramètres : group = groupe dont les paramètres sont à modifier. *
-* callback = éventuelle fonction à appeler ou NULL. *
-* data = données devant accompagner l'appel. *
+* Paramètres : group = groupe dont les conclusions sont attendues. *
+* rel = durée relative à patienter au max. en microsecondes. *
* *
-* Description : Modifie les conditions d'attente des fins d'exécutions. *
+* Description : Attend que toutes les tâches d'un groupe soient traitées. *
* *
-* Retour : - *
+* Retour : Bilan de l'attente : false en cas d'expiration, true sinon. *
* *
-* Remarques : - *
+* Remarques : Cette fonction est originellement dédiée à un usage Python. *
* *
******************************************************************************/
-static void g_work_group_set_extra_wait_callback(GWorkGroup *group, wait_for_incoming_works_cb callback, void *data)
+bool g_work_group_wait_timed_for_completion(GWorkGroup *group, gint64 rel)
{
- group->callback = callback;
- group->data = data;
+ bool result; /* Bilan d'attente à renvoyer */
+ gint64 end_time; /* Borne de fin de l'attente */
-}
+ result = true;
+ g_mutex_lock(&group->mutex);
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Force un réveil d'une attente en cours pour la confirmer. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ end_time = g_get_monotonic_time() + rel;
-static void g_work_group_wake_up_waiters(GWorkGroup *group)
-{
/**
- * Concernant la pose du verrou, se référer aux commentaires de la
- * fonction g_work_group_process().
+ * On attend que :
+ * - la liste des tâches programmées soit vide.
+ * - il n'existe plus de tâche en cours.
+ * - rien n'indique que de nouvelles tâches supplémentaires vont arriver.
*/
- g_mutex_lock(&group->mutex);
-
- g_cond_broadcast(&group->wait_cond);
-
- g_mutex_unlock(&group->mutex);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRAITEMENT DE TACHES DIFFEREES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour le gestionnaire des travaux différés. */
-G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des travaux différés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_class_init(GWorkQueueClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_work_queue_dispose;
- object->finalize = (GObjectFinalizeFunc)g_work_queue_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance à initialiser. *
-* *
-* Description : Initialise une instance de gestionnaire de travaux différés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_init(GWorkQueue *queue)
-{
- queue->generator = 0;
-
- queue->groups = NULL;
- queue->groups_count = 0;
- g_mutex_init(&queue->mutex);
- g_cond_init(&queue->wait_all);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_dispose(GWorkQueue *queue)
-{
- size_t i; /* Boucle de parcours */
-
- g_mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->groups_count; i++)
- g_clear_object(&queue->groups[i]);
-
- g_mutex_unlock(&queue->mutex);
-
- g_mutex_clear(&queue->mutex);
- g_cond_clear(&queue->wait_all);
-
- G_OBJECT_CLASS(g_work_queue_parent_class)->dispose(G_OBJECT(queue));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_queue_finalize(GWorkQueue *queue)
-{
- if (queue->groups != NULL)
- free(queue->groups);
-
- G_OBJECT_CLASS(g_work_queue_parent_class)->finalize(G_OBJECT(queue));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Créé un nouveau gestionnaire de tâches parallèles. *
-* *
-* Retour : Gestionnaire de traitements mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GWorkQueue *g_work_queue_new(void)
-{
- GWorkQueue *result; /* Instance à retourner */
-
- result = g_object_new(G_TYPE_WORK_QUEUE, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Donne l'assurance de l'existence d'un groupe de travail. *
-* *
-* Retour : true si un nouveau groupe a été constitué, false sinon. *
-* *
-* Remarques : Le verrou d'accès doit être posé par l'appelant. *
-* *
-******************************************************************************/
-
-static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id, const guint *count)
-{
- bool found; /* Bilan des recherches */
- size_t i; /* Boucle de parcours */
- GWorkGroup *group; /* Groupe à consulter */
-
- assert(!g_mutex_trylock(&queue->mutex));
-
- found = false;
-
- for (i = 0; i < queue->groups_count && !found; i++)
- {
- group = queue->groups[i];
- found = (g_work_group_get_id(group) == id);
- }
-
- if (!found)
- {
- queue->groups_count++;
- queue->groups = (GWorkGroup **)realloc(queue->groups,
- queue->groups_count * sizeof(GWorkGroup *));
-
- group = g_work_group_new(id, count);
- queue->groups[queue->groups_count - 1] = group;
-
- }
-
- return !found;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* *
-* Description : Constitue un nouveau groupe de travail. *
-* *
-* Retour : Nouvel identifiant unique d'un nouveau groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-wgroup_id_t g_work_queue_define_work_group(GWorkQueue *queue)
-{
- wgroup_id_t result; /* Valeur à retourner */
- bool created; /* Bilan d'une tentative */
-
- g_mutex_lock(&queue->mutex);
-
- do
- {
- result = queue->generator++;
- created = g_work_queue_ensure_group_exists(queue, result, NULL);
- }
- while (!created);
-
- g_mutex_unlock(&queue->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Constitue un nouveau petit groupe de travail. *
-* *
-* Retour : Nouvel identifiant unique d'un nouveau groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *queue, guint count)
-{
- wgroup_id_t result; /* Valeur à retourner */
- bool created; /* Bilan d'une tentative */
-
- g_mutex_lock(&queue->mutex);
-
- do
- {
- result = queue->generator++;
- created = g_work_queue_ensure_group_exists(queue, result, &count);
- }
- while (!created);
-
- g_mutex_unlock(&queue->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Dissout un groupe de travail existant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
-{
- size_t i; /* Boucle de parcours */
- GWorkGroup *group; /* Groupe de travail manipulé */
-#ifndef NDEBUG
- bool found; /* Repérage du groupe visé */
-#endif
-
-#ifndef NDEBUG
- found = false;
-#endif
-
- g_mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->groups_count; i++)
- {
- group = queue->groups[i];
-
- if (g_work_group_get_id(group) == id)
- {
- g_object_unref(G_OBJECT(group));
-
- memmove(&queue->groups[i], &queue->groups[i + 1],
- (queue->groups_count - i - 1) * sizeof(GWorkGroup *));
-
- queue->groups_count--;
- queue->groups = (GWorkGroup **)realloc(queue->groups,
- queue->groups_count * sizeof(GWorkGroup *));
-
-#ifndef NDEBUG
- found = true;
-#endif
-
- break;
-
- }
-
- }
-
- assert(found);
-
- g_cond_broadcast(&queue->wait_all);
-
- g_mutex_unlock(&queue->mutex);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire des actions à mener. *
-* work = nouvelle tâche à programmer, puis effectuer. *
-* id = identifiant du groupe de travail d'affectation. *
-* *
-* Description : Place une nouvelle tâche en attente. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work, wgroup_id_t id)
-{
- GWorkGroup *group; /* Groupe de travail à attendre*/
-
- group = g_work_queue_find_group_for_id(queue, id);
- assert(group != NULL);
-
- g_work_group_schedule(group, work);
-
- g_object_unref(G_OBJECT(group));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Fournit le groupe de travail correspondant à un identifiant. *
-* *
-* Retour : Eventuel groupe existant trouvé ou NULL si aucun. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *queue, wgroup_id_t id)
-{
- GWorkGroup *result; /* Trouvaille à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- g_mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->groups_count; i++)
- if (g_work_group_get_id(queue->groups[i]) == id)
- {
- result = queue->groups[i];
- g_object_ref(G_OBJECT(result));
- break;
- }
-
- g_mutex_unlock(&queue->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Détermine si un groupe est vide de toute programmation. *
-* *
-* Retour : Etat du groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_work_queue_is_empty(GWorkQueue *queue, wgroup_id_t id)
-{
- bool result; /* Etat à retourner */
- GWorkGroup *group; /* Groupe de travail à attendre*/
-
- group = g_work_queue_find_group_for_id(queue, id);
-
- if (group != NULL)
+ while ((g_atomic_int_get(&group->pending) > 0)
+ && !group->force_exit)
{
- result = g_work_group_is_empty(group);
- g_object_unref(G_OBJECT(group));
+ result = g_cond_wait_until(&group->wait_cond, &group->mutex, end_time);
+ if (!result) break;
}
- else
- result = true;
+ g_mutex_unlock(&group->mutex);
return result;
@@ -1217,39 +505,9 @@ bool g_work_queue_is_empty(GWorkQueue *queue, wgroup_id_t id)
/******************************************************************************
* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Attend que toutes les tâches d'un groupe soient traitées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
-{
- GWorkGroup *group; /* Groupe de travail à attendre*/
-
- group = g_work_queue_find_group_for_id(queue, id);
-
- if (group != NULL)
- {
- g_work_group_wait_for_completion(group, queue);
- g_object_unref(G_OBJECT(group));
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* gb_ids = identifiants de groupes globaux. *
-* gb_count = nombre de ces groupes globaux. *
+* Paramètres : group = groupes de travail à manipuler. *
* *
-* Description : Attend que toutes les tâches de tout groupe soient traitées. *
+* Description : Force un réveil d'une attente en cours pour la confirmer. *
* *
* Retour : - *
* *
@@ -1257,97 +515,17 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
* *
******************************************************************************/
-void g_work_queue_wait_for_all_completions(GWorkQueue *queue, const wgroup_id_t *gb_ids, size_t gb_count)
+void g_work_group_wake_up_waiters(GWorkGroup *group)
{
- size_t i; /* Boucle de parcours */
-
- g_mutex_lock(&queue->mutex);
-
- wait_again:
-
- /**
- * Attente d'éventuels groupes isolés.
- */
-
- while (queue->groups_count > gb_count)
- g_cond_wait(&queue->wait_all, &queue->mutex);
-
- g_mutex_unlock(&queue->mutex);
-
/**
- * Attente des groupes principaux.
- */
-
- for (i = 0; i < gb_count; i++)
- g_work_queue_wait_for_completion(queue, gb_ids[i]);
-
- /**
- * Si le groupe par défaut a généré de nouveaux groupes, on recommence !
+ * Concernant la pose du verrou, se référer aux commentaires de la
+ * fonction g_work_group_process().
*/
- g_mutex_lock(&queue->mutex);
-
- if (queue->groups_count > gb_count)
- goto wait_again;
-
- g_mutex_unlock(&queue->mutex);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
-* callback = éventuelle fonction à appeler ou NULL. *
-* data = données devant accompagner l'appel. *
-* *
-* Description : Modifie les conditions d'attente des fins d'exécutions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_set_extra_wait_callback(GWorkQueue *queue, wgroup_id_t id, wait_for_incoming_works_cb callback, void *data)
-{
- GWorkGroup *group; /* Groupe de travail à traiter */
-
- group = g_work_queue_find_group_for_id(queue, id);
-
- if (group != NULL)
- {
- g_work_group_set_extra_wait_callback(group, callback, data);
- g_object_unref(G_OBJECT(group));
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Force un réveil d'une attente en cours pour la confirmer. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_wake_up_waiters(GWorkQueue *queue, wgroup_id_t id)
-{
- GWorkGroup *group; /* Groupe de travail à traiter */
+ g_mutex_lock(&group->mutex);
- group = g_work_queue_find_group_for_id(queue, id);
+ g_cond_broadcast(&group->wait_cond);
- if (group != NULL)
- {
- g_work_group_wake_up_waiters(group);
- g_object_unref(G_OBJECT(group));
- }
+ g_mutex_unlock(&group->mutex);
}
diff --git a/src/glibext/workgroup.h b/src/glibext/workgroup.h
index 89eed12..f40155e 100644
--- a/src/glibext/workgroup.h
+++ b/src/glibext/workgroup.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed.h - prototypes pour la gestion des travaux différés
+ * workgroup.h - prototypes pour la gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,58 +21,22 @@
*/
-#ifndef _GLIBEXT_DELAYED_H
-#define _GLIBEXT_DELAYED_H
+#ifndef _GLIBEXT_WORKGROUP_H
+#define _GLIBEXT_WORKGROUP_H
-#include <glib-object.h>
#include <stdbool.h>
#include <stdint.h>
+#include "helpers.h"
+#include "work.h"
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-#define G_TYPE_DELAYED_WORK g_delayed_work_get_type()
-#define G_DELAYED_WORK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_work_get_type(), GDelayedWork))
-#define G_IS_DELAYED_WORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_work_get_type()))
-#define G_DELAYED_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_WORK, GDelayedWorkClass))
-#define G_IS_DELAYED_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_WORK))
-#define G_DELAYED_WORK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_WORK, GDelayedWorkClass))
+#define G_TYPE_WORK_GROUP (g_work_group_get_type())
-
-/* Travail différé (instance) */
-typedef struct _GDelayedWork GDelayedWork;
-
-/* Travail différé (classe) */
-typedef struct _GDelayedWorkClass GDelayedWorkClass;
-
-
-/* Indique le type défini pour les travaux différés. */
-GType g_delayed_work_get_type(void);
-
-/* Attend la fin de l'exécution d'une tâche donnée. */
-void g_delayed_work_wait_for_completion(GDelayedWork *);
-
-
-
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
-
-#define G_TYPE_WORK_QUEUE g_work_queue_get_type()
-#define G_WORK_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_work_queue_get_type(), GWorkQueue))
-#define G_IS_WORK_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_work_queue_get_type()))
-#define G_WORK_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WORK_QUEUE, GWorkQueueClass))
-#define G_IS_WORK_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WORK_QUEUE))
-#define G_WORK_QUEUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WORK_QUEUE, GWorkQueueClass))
-
-
-/* Gestionnaire des travaux différés (instance) */
-typedef struct _GWorkQueue GWorkQueue;
-
-/* Gestionnaire des travaux différés (classe) */
-typedef struct _GWorkQueueClass GWorkQueueClass;
+DECLARE_GTYPE(GWorkGroup, g_work_group, G, WORK_GROUP);
/**
@@ -83,45 +47,33 @@ typedef struct _GWorkQueueClass GWorkQueueClass;
*/
typedef uint64_t wgroup_id_t;
+/**
+ * Marque de non initialisation.
+ */
+#define INVALID_GROUP_ID 0
-/* Indique le type défini pour le gestionnaire des travaux différés. */
-GType g_work_queue_get_type(void);
-
-/* Créé un nouveau gestionnaire de tâches parallèles. */
-GWorkQueue *g_work_queue_new(void);
-
-/* Constitue un nouveau groupe de travail. */
-wgroup_id_t g_work_queue_define_work_group(GWorkQueue *);
-/* Constitue un nouveau petit groupe de travail. */
-wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *, guint);
+/* Crée un nouveau thread dédié à un type de travaux donné. */
+GWorkGroup *g_work_group_new(wgroup_id_t, guint);
-/* Dissout un groupe de travail existant. */
-void g_work_queue_delete_work_group(GWorkQueue *, wgroup_id_t);
+/* Fournit l'identifiant associé à un groupe de travail. */
+wgroup_id_t g_work_group_get_id(const GWorkGroup *);
-/* Place une nouvelle tâche en attente. */
-void g_work_queue_schedule_work(GWorkQueue *, GDelayedWork *, wgroup_id_t);
+/* Place une nouvelle tâche en attente dans une file dédiée. */
+void g_work_group_schedule(GWorkGroup *, GGenericWork *);
-/* Détermine si un groupe est vide de toute programmation. */
-bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
+/* Détermine si le groupe est vide de toute programmation. */
+bool g_work_group_is_empty(GWorkGroup *);
/* Attend que toutes les tâches d'un groupe soient traitées. */
-void g_work_queue_wait_for_completion(GWorkQueue *, wgroup_id_t);
+void g_work_group_wait_for_completion(GWorkGroup *);
-/* Attend que toutes les tâches de tout groupe soient traitées. */
-void g_work_queue_wait_for_all_completions(GWorkQueue *, const wgroup_id_t *, size_t);
-
-
-/* Etudie le besoin d'attendre d'avantage de prochaines tâches. */
-typedef bool (* wait_for_incoming_works_cb) (GWorkQueue *, wgroup_id_t, void *);
-
-
-/* Modifie les conditions d'attente des fins d'exécutions. */
-void g_work_queue_set_extra_wait_callback(GWorkQueue *, wgroup_id_t, wait_for_incoming_works_cb, void *);
+/* Attend que toutes les tâches d'un groupe soient traitées. */
+bool g_work_group_wait_timed_for_completion(GWorkGroup *, gint64);
/* Force un réveil d'une attente en cours pour la confirmer. */
-void g_work_queue_wake_up_waiters(GWorkQueue *, wgroup_id_t);
+void g_work_group_wake_up_waiters(GWorkGroup *);
-#endif /* _GLIBEXT_DELAYED_H */
+#endif /* _GLIBEXT_WORKGROUP_H */
diff --git a/src/glibext/workqueue-int.h b/src/glibext/workqueue-int.h
index 4f84e86..40afa19 100644
--- a/src/glibext/workqueue-int.h
+++ b/src/glibext/workqueue-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed-int.h - définitions internes pour la gestion des travaux différés
+ * workqueue-int.h - définitions internes pour la gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,55 +21,35 @@
*/
-#ifndef _GLIBEXT_DELAYED_INT_H
-#define _GLIBEXT_DELAYED_INT_H
+#ifndef _GLIBEXT_WORKQUEUE_INT_H
+#define _GLIBEXT_WORKQUEUE_INT_H
-#include "delayed.h"
+#include "workqueue.h"
-#include "notifier.h"
-#include "../common/dllist.h"
-
-
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-
-
-/* Traite un travail programmé. */
-typedef void (* run_task_fc) (GDelayedWork *, GtkStatusStack *);
-
-
-/* Travail différé (instance) */
-struct _GDelayedWork
+/* Gestionnaire des travaux différés (instance) */
+struct _GWorkQueue
{
GObject parent; /* A laisser en premier */
- DL_LIST_ITEM(link); /* Lien vers les maillons */
+ wgroup_id_t generator; /* Générateur d'identifiants */
- bool completed; /* Fin de la tâche ? */
- GMutex mutex; /* Accès à la variable */
- GCond cond; /* Attente de changement */
+ GWorkGroup **groups; /* Files de traitement */
+ size_t groups_count; /* Nombre de files internes */
+ GMutex mutex; /* Verrou pour l'accès */
+ GCond wait_all; /* Réveil d'attente globale */
};
-/* Travail différé (classe) */
-struct _GDelayedWorkClass
+/* Gestionnaire des travaux différés (classe) */
+struct _GWorkQueueClass
{
GObjectClass parent; /* A laisser en premier */
- run_task_fc run; /* Traitement externalisé */
-
- /* Signaux */
-
- void (* work_completed) (GDelayedWork *);
-
};
-#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link)
-#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link)
-
-
-#endif /* _GLIBEXT_DELAYED_INT_H */
+#endif /* _GLIBEXT_WORKQUEUE_INT_H */
diff --git a/src/glibext/workqueue.c b/src/glibext/workqueue.c
index 6b5ac35..fe7f1bb 100644
--- a/src/glibext/workqueue.c
+++ b/src/glibext/workqueue.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed.c - gestion des travaux différés
+ * workqueue.c - gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,149 +21,15 @@
*/
-#include "delayed.h"
+#include "workqueue.h"
#include <assert.h>
-#include <inttypes.h>
#include <malloc.h>
-#include <stdio.h>
-#include <string.h>
-#include "delayed-int.h"
-#include "../core/nproc.h"
-#ifdef INCLUDE_GTK_SUPPORT
-# include "../gui/core/global.h"
-#endif
-
-
-
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-
-
-/* Initialise la classe des travaux différés. */
-static void g_delayed_work_class_init(GDelayedWorkClass *);
-
-/* Initialise une instance de travail différé. */
-static void g_delayed_work_init(GDelayedWork *);
-
-/* Supprime toutes les références externes. */
-static void g_delayed_work_dispose(GDelayedWork *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_delayed_work_finalize(GDelayedWork *);
-
-/* Mène l'opération programmée. */
-static void g_delayed_work_process(GDelayedWork *, GtkStatusStack *);
-
-
-
-/* -------------------------- THREAD DE TRAITEMENTS DEDIES -------------------------- */
-
-
-#define G_TYPE_WORK_GROUP g_work_group_get_type()
-#define G_WORK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_work_group_get_type(), GWorkGroup))
-#define G_IS_WORK_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_work_group_get_type()))
-#define G_WORK_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WORK_GROUP, GWorkGroupClass))
-#define G_IS_WORK_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WORK_GROUP))
-#define G_WORK_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WORK_GROUP, GWorkGroupClass))
-
-
-/* File de traitement pour un type donné (instance) */
-typedef struct _GWorkGroup
-{
- GObject parent; /* A laisser en premier */
-
- wgroup_id_t id; /* Identifiant de travaux menés*/
-
- GDelayedWork *works; /* Tâches à mener à bien */
- GMutex mutex; /* Verrou pour l'accès */
- GCond cond; /* Réveil pour un traitement */
- GCond wait_cond; /* Réveil d'attente de fin */
- gint pending; /* Tâches en cours d'exécution */
-
- GThread **threads; /* Procédure de traitement */
- guint threads_count; /* Nombre de procédures */
- bool force_exit; /* Procédure d'arrêt */
-
- wait_for_incoming_works_cb callback; /* Encadre les attentes de fin */
- void *data; /* Données à associer */
-
-} GWorkGroup;
-
-/* File de traitement pour un type donné (classe) */
-typedef struct _GWorkGroupClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-} GWorkGroupClass;
-
-
-/* Indique le type défini pour les groupes de travail. */
-static GType g_work_group_get_type(void);
-
-/* Initialise la classe des groupes de travail. */
-static void g_work_group_class_init(GWorkGroupClass *);
-
-/* Initialise une instance de groupe de travail. */
-static void g_work_group_init(GWorkGroup *);
+#include "workqueue-int.h"
-/* Supprime toutes les références externes. */
-static void g_work_group_dispose(GWorkGroup *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_work_group_finalize(GWorkGroup *);
-
-/* Crée un nouveau thread dédié à un type de travaux donné. */
-static GWorkGroup *g_work_group_new(wgroup_id_t, const guint *);
-
-/* Fournit l'identifiant associé à un groupe de travail. */
-static wgroup_id_t g_work_group_get_id(const GWorkGroup *);
-
-/* Place une nouvelle tâche en attente dans une file dédiée. */
-static void g_work_group_schedule(GWorkGroup *, GDelayedWork *);
-
-/* Assure le traitement en différé. */
-static void *g_work_group_process(GWorkGroup *);
-
-/* Détermine si le groupe est vide de toute programmation. */
-static bool g_work_group_is_empty(GWorkGroup *);
-
-/* Attend que toutes les tâches d'un groupe soient traitées. */
-static void g_work_group_wait_for_completion(GWorkGroup *, GWorkQueue *);
-
-/* Modifie les conditions d'attente des fins d'exécutions. */
-static void g_work_group_set_extra_wait_callback(GWorkGroup *, wait_for_incoming_works_cb, void *);
-
-/* Force un réveil d'une attente en cours pour la confirmer. */
-static void g_work_group_wake_up_waiters(GWorkGroup *);
-
-
-
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
-
-/* Gestionnaire des travaux différés (instance) */
-struct _GWorkQueue
-{
- GObject parent; /* A laisser en premier */
-
- wgroup_id_t generator; /* Générateur d'identifiants */
-
- GWorkGroup **groups; /* Files de traitement */
- size_t groups_count; /* Nombre de files internes */
- GMutex mutex; /* Verrou pour l'accès */
- GCond wait_all; /* Réveil d'attente globale */
-
-};
-
-/* Gestionnaire des travaux différés (classe) */
-struct _GWorkQueueClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
/* Initialise la classe des travaux différés. */
@@ -179,641 +45,13 @@ static void g_work_queue_dispose(GWorkQueue *);
static void g_work_queue_finalize(GWorkQueue *);
/* Donne l'assurance de l'existence d'un groupe de travail. */
-static bool g_work_queue_ensure_group_exists(GWorkQueue *, wgroup_id_t, const guint *);
+static bool g_work_queue_ensure_group_exists(GWorkQueue *, wgroup_id_t, guint);
/* Fournit le groupe de travail correspondant à un identifiant. */
static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *, wgroup_id_t);
-/* ---------------------------------------------------------------------------------- */
-/* TACHE DIFFEREE DANS LE TEMPS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les travaux différés. */
-G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des travaux différés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_class_init(GDelayedWorkClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_work_dispose;
- object->finalize = (GObjectFinalizeFunc)g_delayed_work_finalize;
-
- g_signal_new("work-completed",
- G_TYPE_DELAYED_WORK,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GDelayedWorkClass, work_completed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = instance à initialiser. *
-* *
-* Description : Initialise une instance de travail différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_init(GDelayedWork *work)
-{
- work->completed = false;
- g_mutex_init(&work->mutex);
- g_cond_init(&work->cond);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_dispose(GDelayedWork *work)
-{
- g_mutex_clear(&work->mutex);
- g_cond_clear(&work->cond);
-
- G_OBJECT_CLASS(g_delayed_work_parent_class)->dispose(G_OBJECT(work));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_finalize(GDelayedWork *work)
-{
- G_OBJECT_CLASS(g_delayed_work_parent_class)->finalize(G_OBJECT(work));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = travail à effectuer. *
-* status = barre de statut à tenir informée. *
-* *
-* Description : Mène l'opération programmée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_work_process(GDelayedWork *work, GtkStatusStack *status)
-{
- G_DELAYED_WORK_GET_CLASS(work)->run(work, status);
-
- g_mutex_lock(&work->mutex);
-
- work->completed = true;
-
- g_cond_signal(&work->cond);
- g_mutex_unlock(&work->mutex);
-
- g_signal_emit_by_name(work, "work-completed");
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : work = travail à surveiller. *
-* *
-* Description : Attend la fin de l'exécution d'une tâche donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_delayed_work_wait_for_completion(GDelayedWork *work)
-{
- g_mutex_lock(&work->mutex);
-
- while (!work->completed)
- g_cond_wait(&work->cond, &work->mutex);
-
- g_mutex_unlock(&work->mutex);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* THREADS DES TRAITEMENTS DEDIES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les groupes de travail. */
-G_DEFINE_TYPE(GWorkGroup, g_work_group, G_TYPE_OBJECT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des groupes de travail. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_class_init(GWorkGroupClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_work_group_dispose;
- object->finalize = (GObjectFinalizeFunc)g_work_group_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = instance à initialiser. *
-* *
-* Description : Initialise une instance de groupe de travail. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_init(GWorkGroup *group)
-{
- group->works = NULL;
-
- g_mutex_init(&group->mutex);
- g_cond_init(&group->cond);
- g_cond_init(&group->wait_cond);
-
- g_atomic_int_set(&group->pending, 0);
-
- group->threads = NULL;
- group->threads_count = 0;
- group->force_exit = false;
-
- group->callback = NULL;
- group->data = NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_dispose(GWorkGroup *group)
-{
- guint i; /* Boucle de parcours */
- GDelayedWork *work; /* Travail à oublier */
-
- group->force_exit = true;
-
- /**
- * Concernant la pose du verrou, se référer aux commentaires de la
- * fonction g_work_group_process().
- */
-
- g_mutex_lock(&group->mutex);
-
- g_cond_broadcast(&group->cond);
-
- g_mutex_unlock(&group->mutex);
-
- for (i = 0; i < group->threads_count; i++)
- g_thread_join(group->threads[i]);
-
- while (!dl_list_empty(group->works))
- {
- work = group->works;
- delayed_work_list_del(work, &group->works);
-
- g_object_unref(G_OBJECT(work));
-
- }
-
- g_mutex_clear(&group->mutex);
- g_cond_clear(&group->cond);
- g_cond_clear(&group->wait_cond);
-
- G_OBJECT_CLASS(g_work_group_parent_class)->dispose(G_OBJECT(group));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_finalize(GWorkGroup *group)
-{
- if (group->threads != NULL)
- free(group->threads);
-
- G_OBJECT_CLASS(g_work_group_parent_class)->finalize(G_OBJECT(group));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : id = identifiant accordé au nouveau groupe. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Crée un nouveau thread dédié à un type de travaux donné. *
-* *
-* Retour : Structure associée au thread mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GWorkGroup *g_work_group_new(wgroup_id_t id, const guint *count)
-{
- GWorkGroup *result; /* Traiteur à retourner */
- guint i; /* Boucle de parcours */
- char name[16]; /* Désignation humaine */
-
- result = g_object_new(G_TYPE_WORK_GROUP, NULL);
-
- result->id = id;
-
- result->threads_count = get_max_online_threads();
-
- if (count != NULL && *count < result->threads_count)
- result->threads_count = *count;
-
- result->threads = (GThread **)calloc(result->threads_count, sizeof(GThread *));
-
- for (i = 0; i < result->threads_count; i++)
- {
- snprintf(name, sizeof(name), "wgrp_%" PRIu64 "-%u", id, i);
-
- result->threads[i] = g_thread_new(name, (GThreadFunc)g_work_group_process, result);
- if (!result->threads[i])
- goto start_error;
-
- }
-
- start_error:
-
- result->threads_count = i;
-
- assert(i > 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = gestionnaire des actions à mener. *
-* *
-* Description : Fournit l'identifiant associé à un groupe de travail. *
-* *
-* Retour : Identifiant unique attribué au groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static wgroup_id_t g_work_group_get_id(const GWorkGroup *group)
-{
- return group->id;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = gestionnaire des actions à mener. *
-* work = nouvelle tâche à programmer, puis effectuer. *
-* *
-* Description : Place une nouvelle tâche en attente dans une file dédiée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_schedule(GWorkGroup *group, GDelayedWork *work)
-{
- g_mutex_lock(&group->mutex);
-
- g_atomic_int_inc(&group->pending);
-
- delayed_work_list_add_tail(work, &group->works);
-
- g_cond_signal(&group->cond);
-
- g_mutex_unlock(&group->mutex);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = gestionnaire des actions à mener. *
-* *
-* Description : Assure le traitement en différé. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void *g_work_group_process(GWorkGroup *group)
-{
- GDelayedWork *work; /* Traitement à mener */
- GtkStatusStack *status; /* Zone d'info éventuelle */
-
- while (1)
- {
- g_mutex_lock(&group->mutex);
-
- while (dl_list_empty(group->works) && !group->force_exit)
- g_cond_wait(&group->cond, &group->mutex);
-
- if (group->force_exit)
- {
- g_mutex_unlock(&group->mutex);
- break;
- }
-
- work = group->works;
- delayed_work_list_del(work, &group->works);
-
- g_mutex_unlock(&group->mutex);
-
-#ifdef INCLUDE_GTK_SUPPORT
- status = get_global_status();
-#else
- status = NULL;
-#endif
- g_delayed_work_process(work, status);
-
- g_object_unref(G_OBJECT(work));
-
- /**
- * Verrou ou pas verrou ?
- *
- * La documentation de la GLib indique que ce n'est pas nécessaire :
- *
- * '''
- * It is good practice to lock the same mutex as the waiting threads
- * while calling this function, though not required.
- * '''
- *
- * Ce conseil se trouve verbatim à l'adresse :
- *
- * https://developer.gnome.org/glib/stable/glib-Threads.html#g-cond-broadcast
- *
- * Dans la pratique, il peut arriver que l'attente de la fonction
- * g_work_group_wait_for_completion() ne soit jamais interrompue.
- *
- * La documentation POSIX est un peu plus orientée :
- *
- * '''
- * The pthread_cond_broadcast() functions may be called by a thread
- * whether or not it currently owns the mutex that threads calling
- * pthread_cond_wait() have associated with the condition variable
- * during their waits; however, if predictable scheduling behavior is
- * required, then that mutex shall be locked by the thread calling
- * pthread_cond_broadcast().
- * '''
- *
- * Ce passage complet est consultable à l'adresse :
- *
- * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_broadcast.html
- *
- * La page de manuel pthread_cond_broadcast(3) est quant à elle plus
- * directrice : aucun complément d'information sur le sujet n'est fourni
- * et les exemples associés utilisent implicement un verrou pendant
- * sont appel.
- */
-
- g_mutex_lock(&group->mutex);
-
- if (g_atomic_int_dec_and_test(&group->pending))
- g_cond_broadcast(&group->wait_cond);
-
- g_mutex_unlock(&group->mutex);
-
- }
-
- return NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = gestionnaire des actions à consulter. *
-* *
-* Description : Détermine si le groupe est vide de toute programmation. *
-* *
-* Retour : Etat du groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_work_group_is_empty(GWorkGroup *group)
-{
- bool result; /* Etat à retourner */
-
- /**
- * Pour que le résultat soit exploitable, il ne doit pas varier
- * en dehors de la zone couverte par le verrou du groupe avant
- * son utilisation par l'appelant.
- *
- * Il doit donc logiquement y avoir un autre verrou en amont et,
- * comme à priori on ne devrait pas bloquer les groupes principaux
- * pour un traitement particulier, cette procédure ne devrait concerner
- * que des groupes dynamiques.
- */
-
- g_mutex_lock(&group->mutex);
-
- result = dl_list_empty(group->works);
-
- g_mutex_unlock(&group->mutex);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = groupe dont les conclusions sont attendues. *
-* queue = queue d'appartenance pour les appels externes. *
-* *
-* Description : Attend que toutes les tâches d'un groupe soient traitées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_wait_for_completion(GWorkGroup *group, GWorkQueue *queue)
-{
- wait_for_incoming_works_cb callback; /* Procédure complémentaire */
-
- bool no_extra_check(GWorkQueue *_q, wgroup_id_t _id, void *_data)
- {
- return false;
- }
-
- callback = group->callback != NULL ? group->callback : no_extra_check;
-
- g_mutex_lock(&group->mutex);
-
- /**
- * On attend que :
- * - la liste des tâches programmées soit vide.
- * - il n'existe plus de tâche en cours.
- * - rien n'indique que de nouvelles tâches supplémentaires vont arriver.
- */
-
- while ((g_atomic_int_get(&group->pending) > 0 || callback(queue, group->id, group->data))
- && !group->force_exit)
- {
- g_cond_wait(&group->wait_cond, &group->mutex);
- }
-
- g_mutex_unlock(&group->mutex);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : group = groupe dont les paramètres sont à modifier. *
-* callback = éventuelle fonction à appeler ou NULL. *
-* data = données devant accompagner l'appel. *
-* *
-* Description : Modifie les conditions d'attente des fins d'exécutions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_set_extra_wait_callback(GWorkGroup *group, wait_for_incoming_works_cb callback, void *data)
-{
- group->callback = callback;
- group->data = data;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
-* *
-* Description : Force un réveil d'une attente en cours pour la confirmer. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_work_group_wake_up_waiters(GWorkGroup *group)
-{
- /**
- * Concernant la pose du verrou, se référer aux commentaires de la
- * fonction g_work_group_process().
- */
-
- g_mutex_lock(&group->mutex);
-
- g_cond_broadcast(&group->wait_cond);
-
- g_mutex_unlock(&group->mutex);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRAITEMENT DE TACHES DIFFEREES */
-/* ---------------------------------------------------------------------------------- */
-
-
/* Indique le type défini pour le gestionnaire des travaux différés. */
G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT);
@@ -946,7 +184,7 @@ GWorkQueue *g_work_queue_new(void)
* *
* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
* id = identifiant d'un groupe de travail. *
-* count = quantité de threads à allouer. *
+* count = quantité de threads à allouer (0 pour un défaut). *
* *
* Description : Donne l'assurance de l'existence d'un groupe de travail. *
* *
@@ -956,7 +194,7 @@ GWorkQueue *g_work_queue_new(void)
* *
******************************************************************************/
-static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id, const guint *count)
+static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id, guint count)
{
bool found; /* Bilan des recherches */
size_t i; /* Boucle de parcours */
@@ -975,8 +213,7 @@ static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id,
if (!found)
{
queue->groups_count++;
- queue->groups = (GWorkGroup **)realloc(queue->groups,
- queue->groups_count * sizeof(GWorkGroup *));
+ queue->groups = realloc(queue->groups, queue->groups_count * sizeof(GWorkGroup *));
group = g_work_group_new(id, count);
queue->groups[queue->groups_count - 1] = group;
@@ -991,6 +228,7 @@ static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id,
/******************************************************************************
* *
* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
+* count = quantité de threads à allouer (0 pour un défaut). *
* *
* Description : Constitue un nouveau groupe de travail. *
* *
@@ -1000,7 +238,7 @@ static bool g_work_queue_ensure_group_exists(GWorkQueue *queue, wgroup_id_t id,
* *
******************************************************************************/
-wgroup_id_t g_work_queue_define_work_group(GWorkQueue *queue)
+wgroup_id_t g_work_queue_define_group(GWorkQueue *queue, guint count)
{
wgroup_id_t result; /* Valeur à retourner */
bool created; /* Bilan d'une tentative */
@@ -1009,42 +247,13 @@ wgroup_id_t g_work_queue_define_work_group(GWorkQueue *queue)
do
{
- result = queue->generator++;
- created = g_work_queue_ensure_group_exists(queue, result, NULL);
- }
- while (!created);
+ result = ++queue->generator;
- g_mutex_unlock(&queue->mutex);
+ if (result == INVALID_GROUP_ID)
+ continue;
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
-* count = quantité de threads à allouer. *
-* *
-* Description : Constitue un nouveau petit groupe de travail. *
-* *
-* Retour : Nouvel identifiant unique d'un nouveau groupe de travail. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ created = g_work_queue_ensure_group_exists(queue, result, count);
-wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *queue, guint count)
-{
- wgroup_id_t result; /* Valeur à retourner */
- bool created; /* Bilan d'une tentative */
-
- g_mutex_lock(&queue->mutex);
-
- do
- {
- result = queue->generator++;
- created = g_work_queue_ensure_group_exists(queue, result, &count);
}
while (!created);
@@ -1068,7 +277,7 @@ wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *queue, guint count)
* *
******************************************************************************/
-void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
+void g_work_queue_delete_group(GWorkQueue *queue, wgroup_id_t id)
{
size_t i; /* Boucle de parcours */
GWorkGroup *group; /* Groupe de travail manipulé */
@@ -1088,14 +297,13 @@ void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
if (g_work_group_get_id(group) == id)
{
- g_object_unref(G_OBJECT(group));
+ unref_object(group);
memmove(&queue->groups[i], &queue->groups[i + 1],
(queue->groups_count - i - 1) * sizeof(GWorkGroup *));
queue->groups_count--;
- queue->groups = (GWorkGroup **)realloc(queue->groups,
- queue->groups_count * sizeof(GWorkGroup *));
+ queue->groups = realloc(queue->groups, queue->groups_count * sizeof(GWorkGroup *));
#ifndef NDEBUG
found = true;
@@ -1124,22 +332,31 @@ void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
* *
* Description : Place une nouvelle tâche en attente. *
* *
-* Retour : - *
+* Retour : Bilan, qui correspond à l'existence du groupe ciblé. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_work_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work, wgroup_id_t id)
+bool g_work_queue_schedule(GWorkQueue *queue, GGenericWork *work, wgroup_id_t id)
{
+ bool result; /* Bilan à retourner */
GWorkGroup *group; /* Groupe de travail à attendre*/
group = g_work_queue_find_group_for_id(queue, id);
assert(group != NULL);
- g_work_group_schedule(group, work);
+ result = (group != NULL);
- g_object_unref(G_OBJECT(group));
+ if (result)
+ {
+ g_work_group_schedule(group, work);
+
+ unref_object(group);
+
+ }
+
+ return result;
}
@@ -1170,7 +387,7 @@ static GWorkGroup *g_work_queue_find_group_for_id(GWorkQueue *queue, wgroup_id_t
if (g_work_group_get_id(queue->groups[i]) == id)
{
result = queue->groups[i];
- g_object_ref(G_OBJECT(result));
+ ref_object(result);
break;
}
@@ -1204,7 +421,7 @@ bool g_work_queue_is_empty(GWorkQueue *queue, wgroup_id_t id)
if (group != NULL)
{
result = g_work_group_is_empty(group);
- g_object_unref(G_OBJECT(group));
+ unref_object(group);
}
else
@@ -1236,8 +453,8 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
if (group != NULL)
{
- g_work_group_wait_for_completion(group, queue);
- g_object_unref(G_OBJECT(group));
+ g_work_group_wait_for_completion(group);
+ unref_object(group);
}
}
@@ -1245,6 +462,40 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
/******************************************************************************
* *
+* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail. *
+* id = identifiant d'un groupe de travail. *
+* rel = durée relative à patienter au max. en microsecondes. *
+* *
+* Description : Attend que toutes les tâches d'un groupe soient traitées. *
+* *
+* Retour : Bilan de l'attente : false en cas d'expiration, true sinon. *
+* *
+* Remarques : Cette fonction est originellement dédiée à un usage Python. *
+* *
+******************************************************************************/
+
+bool g_work_queue_wait_timed_for_completion(GWorkQueue *queue, wgroup_id_t id, gint64 rel)
+{
+ bool result; /* Bilan d'attente à renvoyer */
+ GWorkGroup *group; /* Groupe de travail à attendre*/
+
+ group = g_work_queue_find_group_for_id(queue, id);
+
+ if (group != NULL)
+ {
+ result = g_work_group_wait_timed_for_completion(group, rel);
+ unref_object(group);
+ }
+ else
+ result = true;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
* gb_ids = identifiants de groupes globaux. *
* gb_count = nombre de ces groupes globaux. *
@@ -1299,36 +550,6 @@ void g_work_queue_wait_for_all_completions(GWorkQueue *queue, const wgroup_id_t
* *
* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
* id = identifiant d'un groupe de travail. *
-* callback = éventuelle fonction à appeler ou NULL. *
-* data = données devant accompagner l'appel. *
-* *
-* Description : Modifie les conditions d'attente des fins d'exécutions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_work_queue_set_extra_wait_callback(GWorkQueue *queue, wgroup_id_t id, wait_for_incoming_works_cb callback, void *data)
-{
- GWorkGroup *group; /* Groupe de travail à traiter */
-
- group = g_work_queue_find_group_for_id(queue, id);
-
- if (group != NULL)
- {
- g_work_group_set_extra_wait_callback(group, callback, data);
- g_object_unref(G_OBJECT(group));
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : queue = gestionnaire de l'ensemble des groupes de travail.*
-* id = identifiant d'un groupe de travail. *
* *
* Description : Force un réveil d'une attente en cours pour la confirmer. *
* *
@@ -1347,7 +568,7 @@ void g_work_queue_wake_up_waiters(GWorkQueue *queue, wgroup_id_t id)
if (group != NULL)
{
g_work_group_wake_up_waiters(group);
- g_object_unref(G_OBJECT(group));
+ unref_object(group);
}
}
diff --git a/src/glibext/workqueue.h b/src/glibext/workqueue.h
index 89eed12..963d86a 100644
--- a/src/glibext/workqueue.h
+++ b/src/glibext/workqueue.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * delayed.h - prototypes pour la gestion des travaux différés
+ * workqueue.h - prototypes pour la gestion des travaux différés
*
- * Copyright (C) 2009-2018 Cyrille Bagard
+ * Copyright (C) 2009-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,86 +21,34 @@
*/
-#ifndef _GLIBEXT_DELAYED_H
-#define _GLIBEXT_DELAYED_H
+#ifndef _GLIBEXT_WORKQUEUE_H
+#define _GLIBEXT_WORKQUEUE_H
-#include <glib-object.h>
#include <stdbool.h>
-#include <stdint.h>
+#include "helpers.h"
+#include "workgroup.h"
-/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
-#define G_TYPE_DELAYED_WORK g_delayed_work_get_type()
-#define G_DELAYED_WORK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_work_get_type(), GDelayedWork))
-#define G_IS_DELAYED_WORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_work_get_type()))
-#define G_DELAYED_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_WORK, GDelayedWorkClass))
-#define G_IS_DELAYED_WORK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_WORK))
-#define G_DELAYED_WORK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_WORK, GDelayedWorkClass))
+#define G_TYPE_WORK_QUEUE (g_work_queue_get_type())
+DECLARE_GTYPE(GWorkQueue, g_work_queue, G, WORK_QUEUE);
-/* Travail différé (instance) */
-typedef struct _GDelayedWork GDelayedWork;
-
-/* Travail différé (classe) */
-typedef struct _GDelayedWorkClass GDelayedWorkClass;
-
-
-/* Indique le type défini pour les travaux différés. */
-GType g_delayed_work_get_type(void);
-
-/* Attend la fin de l'exécution d'une tâche donnée. */
-void g_delayed_work_wait_for_completion(GDelayedWork *);
-
-
-
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
-
-#define G_TYPE_WORK_QUEUE g_work_queue_get_type()
-#define G_WORK_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_work_queue_get_type(), GWorkQueue))
-#define G_IS_WORK_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_work_queue_get_type()))
-#define G_WORK_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WORK_QUEUE, GWorkQueueClass))
-#define G_IS_WORK_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WORK_QUEUE))
-#define G_WORK_QUEUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WORK_QUEUE, GWorkQueueClass))
-
-
-/* Gestionnaire des travaux différés (instance) */
-typedef struct _GWorkQueue GWorkQueue;
-
-/* Gestionnaire des travaux différés (classe) */
-typedef struct _GWorkQueueClass GWorkQueueClass;
-
-
-/**
- * Identifiant unique pour groupe de travail.
- *
- * Le nombre de bits est forcé à 64 bits car glib-genmarshal ne reconnait
- * pas explicitement le type 'unsigned long long'.
- */
-typedef uint64_t wgroup_id_t;
-
-
-/* Indique le type défini pour le gestionnaire des travaux différés. */
-GType g_work_queue_get_type(void);
/* Créé un nouveau gestionnaire de tâches parallèles. */
GWorkQueue *g_work_queue_new(void);
/* Constitue un nouveau groupe de travail. */
-wgroup_id_t g_work_queue_define_work_group(GWorkQueue *);
-
-/* Constitue un nouveau petit groupe de travail. */
-wgroup_id_t g_work_queue_define_tiny_work_group(GWorkQueue *, guint);
+wgroup_id_t g_work_queue_define_group(GWorkQueue *, guint);
/* Dissout un groupe de travail existant. */
-void g_work_queue_delete_work_group(GWorkQueue *, wgroup_id_t);
+void g_work_queue_delete_group(GWorkQueue *, wgroup_id_t);
/* Place une nouvelle tâche en attente. */
-void g_work_queue_schedule_work(GWorkQueue *, GDelayedWork *, wgroup_id_t);
+bool g_work_queue_schedule(GWorkQueue *, GGenericWork *, wgroup_id_t);
/* Détermine si un groupe est vide de toute programmation. */
bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
@@ -108,20 +56,15 @@ bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
/* Attend que toutes les tâches d'un groupe soient traitées. */
void g_work_queue_wait_for_completion(GWorkQueue *, wgroup_id_t);
+/* Attend que toutes les tâches d'un groupe soient traitées. */
+bool g_work_queue_wait_timed_for_completion(GWorkQueue *, wgroup_id_t, gint64);
+
/* Attend que toutes les tâches de tout groupe soient traitées. */
void g_work_queue_wait_for_all_completions(GWorkQueue *, const wgroup_id_t *, size_t);
-
-/* Etudie le besoin d'attendre d'avantage de prochaines tâches. */
-typedef bool (* wait_for_incoming_works_cb) (GWorkQueue *, wgroup_id_t, void *);
-
-
-/* Modifie les conditions d'attente des fins d'exécutions. */
-void g_work_queue_set_extra_wait_callback(GWorkQueue *, wgroup_id_t, wait_for_incoming_works_cb, void *);
-
/* Force un réveil d'une attente en cours pour la confirmer. */
void g_work_queue_wake_up_waiters(GWorkQueue *, wgroup_id_t);
-#endif /* _GLIBEXT_DELAYED_H */
+#endif /* _GLIBEXT_WORKQUEUE_H */
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index c9445e6..c6908dd 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -13,15 +13,11 @@ libgtkext_la_SOURCES = \
gtkblockdisplay.h gtkblockdisplay.c \
gtkdockable-int.h \
gtkdockable.h gtkdockable.c \
- gtkdockstation.h gtkdockstation.c \
gtkgraphdisplay.h gtkgraphdisplay.c \
- gtkstatusstack.h gtkstatusstack.c \
hexdisplay.h hexdisplay.c \
named-int.h \
named.h named.c \
- resources.h resources.c \
support.h support.c \
- tiledgrid.h tiledgrid.c \
tmgt.h tmgt.c
libgtkext_la_LIBADD = \
@@ -30,9 +26,19 @@ libgtkext_la_LIBADD = \
libgtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+IMG_PATH = ../../data/images
+
RES_FILES = \
+ grid.ui \
+ dockstation.ui \
hexview.css \
- hexview.ui
+ hexview.ui \
+ launcher.ui \
+ statusstack.ui \
+ $(IMG_PATH)/nolock-symbolic.svg \
+ $(IMG_PATH)/locked-symbolic.svg \
+ $(IMG_PATH)/unlocked-symbolic.svg \
+ tweak.ui
libgtkext4_la_SOURCES = \
area-int.h \
@@ -41,19 +47,36 @@ libgtkext4_la_SOURCES = \
bufferview.h bufferview.c \
contentview-int.h \
contentview.h contentview.c \
+ dockstation-int.h \
+ dockstation.h dockstation.c \
+ grid-int.h \
+ grid.h grid.c \
+ helpers.h \
hexview-int.h \
hexview.h hexview.c \
- resources.h resources.c
+ launcher-int.h \
+ launcher.h launcher.c \
+ panel-int.h \
+ panel.h panel.c \
+ resources.h resources.c \
+ statusstack-int.h \
+ statusstack.h statusstack.c \
+ tweak-int.h \
+ tweak.h tweak.c
libgtkext4_la_CFLAGS = $(LIBGTK4_CFLAGS)
+libgtkext4_la_LIBADD = \
+ bindings/libgtkextbindings.la
+
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
-dev_HEADERS = $(libgtkext_la_SOURCES:%c=)
+dev_HEADERS = $(libgtkext4_la_SOURCES:%c=)
#SUBDIRS = graph
+SUBDIRS = bindings
resources.c: gresource.xml $(RES_FILES)
diff --git a/src/gtkext/area.c b/src/gtkext/area.c
index 3c59a59..3c573b2 100644
--- a/src/gtkext/area.c
+++ b/src/gtkext/area.c
@@ -85,6 +85,8 @@ static void gtk_composing_area_class_init(GtkComposingAreaClass *class)
widget = GTK_WIDGET_CLASS(class);
+ gtk_widget_class_set_css_name(widget, "comparea");
+
widget->snapshot = gtk_composing_area_snapshot;
}
diff --git a/src/gtkext/bindings/Makefile.am b/src/gtkext/bindings/Makefile.am
new file mode 100644
index 0000000..71e770d
--- /dev/null
+++ b/src/gtkext/bindings/Makefile.am
@@ -0,0 +1,42 @@
+
+EXTRA_DIST = \
+ generated-enums.c.template \
+ generated-enums.h.template
+
+
+noinst_LTLIBRARIES = libgtkextbindings.la
+
+
+nodist_libgtkextbindings_la_SOURCES = \
+ grid-enums.h grid-enums.c
+
+libgtkextbindings_la_CFLAGS = $(LIBGTK4_CFLAGS)
+
+
+BUILT_SOURCES = $(nodist_libgtkextbindings_la_SOURCES)
+CLEANFILES = $(nodist_libgtkextbindings_la_SOURCES)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(nodist_libgtkextbindings_la_SOURCES:%c=)
+
+
+grid-enums.c: ../../gtkext/grid.h generated-enums.c.template
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#include \"$(subst .c,.h,$@)\"\n" \
+ --template=$(srcdir)/generated-enums.c.template \
+ --output=$(srcdir)/$@ \
+ $<
+
+grid-enums.h: ../../gtkext/grid.h generated-enums.h.template
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#ifndef _GTKEXT_BINDINGS_GRID_ENUM_H\n" \
+ --fhead "#define _GTKEXT_BINDINGS_GRID_ENUM_H\n" \
+ --fhead "\n" \
+ --fhead "#include \"$<\"\n" \
+ --fhead "\n" \
+ --ftail "#endif /* _GTKEXT_BINDINGS_GRID_ENUM_H */\n" \
+ --template=$(srcdir)/generated-enums.h.template \
+ --output=$(srcdir)/$@ \
+ $<
diff --git a/src/gtkext/bindings/generated-enums.c.template b/src/gtkext/bindings/generated-enums.c.template
new file mode 100644
index 0000000..8f54149
--- /dev/null
+++ b/src/gtkext/bindings/generated-enums.c.template
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+/*** BEGIN file-header ***/
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* Enumerations de "@filename@" */
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+
+GType @enum_name@_get_type(void)
+{
+ static gsize static_g_@type@_type_id;
+
+ if (g_once_init_enter(&static_g_@type@_type_id)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ {@VALUENAME@, "@VALUENAME@", "@valuenick@"},
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+
+ GType g_@type@_type_id = g_@type@_register_static(
+ g_intern_static_string("@EnumName@"), values);
+
+ g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id);
+ }
+
+ return static_g_@type@_type_id;
+}
+
+/*** END value-tail ***/
diff --git a/src/gtkext/bindings/generated-enums.h.template b/src/gtkext/bindings/generated-enums.h.template
new file mode 100644
index 0000000..58c772d
--- /dev/null
+++ b/src/gtkext/bindings/generated-enums.h.template
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2023-2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+/*** BEGIN file-header ***/
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type(void) G_GNUC_CONST;
+#define @ENUMPREFIX@_@ENUMSHORT@_TYPE (@enum_name@_get_type())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+/*** END file-tail ***/
diff --git a/src/gtkext/bufferview.c b/src/gtkext/bufferview.c
index 4a700c3..13c2632 100644
--- a/src/gtkext/bufferview.c
+++ b/src/gtkext/bufferview.c
@@ -33,10 +33,10 @@
/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
-/* Procède à l'initialisation de l'afficheur de tampons. */
+/* Initialise la classe des afficheurs de tampons. */
static void gtk_buffer_view_class_init(GtkBufferViewClass *);
-/* Procède à l'initialisation de l'afficheur de tampons. */
+/* Initialise une instance d'afficheur de tampons. */
static void gtk_buffer_view_init(GtkBufferView *);
/* Supprime toutes les références externes. */
@@ -72,7 +72,7 @@ G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_CONTENT_VIEW);
* *
* Paramètres : class = classe GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur de tampons. *
+* Description : Initialise la classe des afficheurs de tampons. *
* *
* Retour : - *
* *
@@ -146,9 +146,9 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
/******************************************************************************
* *
-* Paramètres : display = composant GTK à initialiser. *
+* Paramètres : view = composant GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur de tampons. *
+* Description : Initialise une instance d'afficheur de tampons. *
* *
* Retour : - *
* *
@@ -168,7 +168,7 @@ static void gtk_buffer_view_init(GtkBufferView *view)
/******************************************************************************
* *
-* Paramètres : display = instance d'objet GLib à traiter. *
+* Paramètres : view = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -208,7 +208,7 @@ static void gtk_buffer_view_dispose(GtkBufferView *view)
/******************************************************************************
* *
-* Paramètres : display = instance d'objet Gtk à traiter. *
+* Paramètres : view = instance d'objet Gtk à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -279,9 +279,9 @@ GBufferView *gtk_buffer_view_get_view(const GtkBufferView *view)
/******************************************************************************
* *
-* Paramètres : widget = composant GTK à examiner. *
-* width = largeur affectée au composant graphique. *
-* height = hauteur affectée au composant graphique. *
+* Paramètres : widget = composant GTK à examiner. *
+* width = largeur affectée au composant graphique. *
+* height = hauteur affectée au composant graphique. *
* baseline = ligne de base affectée au composant graphique. *
* *
* Description : Prend acte de la taille allouée au composant d'affichage. *
diff --git a/src/gtkext/dockstation-int.h b/src/gtkext/dockstation-int.h
new file mode 100644
index 0000000..17ed828
--- /dev/null
+++ b/src/gtkext/dockstation-int.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dockstation.h - prototypes internes pour la manipulation et l'affichage de composants rassemblés
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_DOCKSTATION_INT_H
+#define _GTKEXT_DOCKSTATION_INT_H
+
+
+#include "dockstation.h"
+
+
+
+/* Station de réception pour concentration d'éléments (instance) */
+struct _GtkDockStation
+{
+ GtkBox parent; /* A laisser en premier */
+
+ GtkOrientation orientation; /* Spécification d'orientation */
+
+ GtkWidget *tabs; /* Bascule entre panneaux */
+ GtkWidget *toolbar; /* Boutons d'action */
+ GtkWidget *sep1; /* Séparateur #1 */
+ GtkStack *stack; /* Pile de panneaux affichés */
+ GtkWidget *sep2; /* Séparateur #2 */
+
+ GtkTiledPanel *def_panel; /* Eventuel panneau à maintenir*/
+
+};
+
+/* Station de réception pour concentration d'éléments (classe) */
+struct _GtkDockStationClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+ /* Signaux */
+
+ void (* panel_docked) (GtkDockStation *, GtkTiledPanel *);
+ void (* panel_undocked) (GtkDockStation *, GtkTiledPanel *);
+
+ void (* switch_widget) (GtkDockStation *, GtkWidget *);
+
+ void (* menu_requested) (GtkDockStation *, GtkWidget *);
+ void (* close_requested) (GtkDockStation *, GtkWidget *);
+
+};
+
+
+
+#endif /* _GTKEXT_DOCKSTATION_INT_H */
diff --git a/src/gtkext/dockstation.c b/src/gtkext/dockstation.c
new file mode 100644
index 0000000..80bae75
--- /dev/null
+++ b/src/gtkext/dockstation.c
@@ -0,0 +1,1052 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dockstation.c - manipulation et l'affichage de composants rassemblés
+ *
+ * Copyright (C) 2012-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "dockstation.h"
+
+
+#include "dockstation-int.h"
+
+
+
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _DockStationProperty {
+
+ PROP_0, /* Réservé */
+
+ /* Interface GtkOrientable */
+ PROP_ORIENTATION,
+
+ N_PROPERTIES = PROP_ORIENTATION
+
+} DockStationProperty;
+
+//static GParamSpec *_dock_station_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Procède à l'initialisation de l'afficheur concentré. */
+static void gtk_dock_station_class_init(GtkDockStationClass *);
+
+/* Procède à l'initialisation du support d'affichage concentré. */
+static void gtk_dock_station_init(GtkDockStation *);
+
+/* Supprime toutes les références externes. */
+static void gtk_dock_station_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_dock_station_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_dock_station_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_dock_station_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE DU COMPOSANT GTK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant d'affichage concentré. */
+G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_GRID)
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_class_init(GtkDockStationClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_dock_station_dispose;
+ object->finalize = gtk_dock_station_finalize;
+ object->set_property = gtk_dock_station_set_property;
+ object->get_property = gtk_dock_station_get_property;
+
+ //g_object_class_install_properties(object, N_PROPERTIES, _dock_station_properties);
+ g_object_class_override_property(object, PROP_ORIENTATION, "orientation");
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/dockstation.ui");
+
+ //gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press));
+
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, tabs);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, toolbar);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, sep1);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, stack);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, sep2);
+
+ g_signal_new("panel-docked",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, panel_docked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("panel-undocked",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, panel_undocked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ /*
+ g_signal_new("switch-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, switch_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("menu-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, menu_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("close-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, close_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+ */
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation du support d'affichage concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_init(GtkDockStation *station)
+{
+ gtk_widget_init_template(GTK_WIDGET(station));
+
+ station->orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ station->def_panel = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_dispose(GObject *object)
+{
+ GtkDockStation *station; /* Version spécialisée */
+
+ station = GTK_DOCK_STATION(object);
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION);
+
+ g_clear_object(&station->def_panel);
+
+ G_OBJECT_CLASS(gtk_dock_station_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_dock_station_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau composant pour support d'affichage concentré.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_dock_station_new(void)
+{
+ GtkWidget *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_DOCK_STATION, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à compléter. *
+* panel = nouveau panneau à afficher. *
+* *
+* Description : Ajoute un panneau à un groupe de tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_add_panel(GtkDockStation *station, GtkTiledPanel *panel)
+{
+ GtkStackPage *page; /* Nouvelle page insérée */
+
+ page = gtk_stack_add_child(station->stack, GTK_WIDGET(panel));
+
+ if (0) // TODO
+ gtk_stack_page_set_title(page, "settings");
+
+ else
+ gtk_stack_page_set_icon_name(page, "logs-symbolic");
+
+ gtk_stack_set_visible_child(station->stack, GTK_WIDGET(panel));
+
+
+ g_signal_emit_by_name(station, "panel-docked", panel);
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à compléter. *
+* panel = nouveau panneau à afficher. *
+* *
+* Description : Ajoute un panneau à conserver à un groupe de tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_keep_panel(GtkDockStation *station, GtkTiledPanel *panel)
+{
+ bool visible; /* Visibilité des barres */
+
+ g_clear_object(&station->def_panel);
+
+ if (panel != NULL)
+ {
+ station->def_panel = panel;
+ ref_object(panel);
+
+ if (gtk_stack_get_page(station->stack, GTK_WIDGET(panel)) == NULL)
+ gtk_dock_station_add_panel(station, panel);
+
+ }
+
+ visible = (station->def_panel == NULL);
+
+ gtk_widget_set_visible(station->tabs, visible);
+ gtk_widget_set_visible(station->toolbar, visible);
+ gtk_widget_set_visible(station->sep1, visible);
+ gtk_widget_set_visible(station->sep2, visible && station->orientation == GTK_ORIENTATION_HORIZONTAL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à consulter. *
+* *
+* Description : Indique si la station d'accueil contient au moins un panneau.*
+* *
+* Retour : true si aucun panneau n'est intégré, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_dock_station_is_empty(const GtkDockStation *station)
+{
+ bool result; /* Bilan à retourner */
+ GtkSelectionModel *model; /* Modèle pour la pile */
+ guint count; /* Nombre de panneaux présents */
+
+ model = gtk_stack_get_pages(station->stack);
+
+ count = g_list_model_get_n_items(G_LIST_MODEL(model));
+
+ result = (count == 0);
+
+ unref_object(model);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_notify_new_main_panel_state(const GtkDockStation *station, GtkTiledPanel *main, bool activated)
+{
+ GListModel *list; /* Liste de pages à parcourir */
+ guint count; /* Nombre de pages */
+ guint i; /* Boucle de parcours */
+ GtkStackPage *page; /* Page à consulter */
+ GtkWidget *panel; /* Panneau intégré */
+
+ list = G_LIST_MODEL(gtk_stack_get_pages(station->stack));
+
+ count = g_list_model_get_n_items(list);
+
+ for (i = 0; i < count; i++)
+ {
+ page = GTK_STACK_PAGE(g_list_model_get_object(list, i));
+ if (page == NULL) continue;
+
+ panel = gtk_stack_page_get_child(page);
+
+ gtk_tiled_panel_notify_new_main_panel_state(GTK_TILED_PANEL(panel), main, activated);
+
+ unref_object(page);
+
+ }
+
+ unref_object(list);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkDockStation *station; /* Version spécialisée */
+ GtkOrientation orientation; /* Spécification d'orientation */
+ GtkLayoutManager *layout; /* Gestionnaire de disposition */
+ GtkLayoutChild *child_layout; /* Disposition de composant */
+
+ station = GTK_DOCK_STATION(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+
+ orientation = g_value_get_enum(value);
+
+ if (station->orientation != orientation)
+ {
+ station->orientation = orientation;
+
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(station->tabs), orientation);
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(station->toolbar), orientation);
+
+ layout = gtk_widget_get_layout_manager(GTK_WIDGET(object));
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ g_object_set(G_OBJECT(station->tabs),
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ g_object_set(G_OBJECT(station->toolbar),
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 1,
+ "row", 0,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 0,
+ "row", 1,
+ "column-span", 2,
+ NULL);
+
+ gtk_widget_set_visible(station->sep2, FALSE);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack));
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 0,
+ "row", 2,
+ "column-span", 2,
+ NULL);
+
+ }
+ else
+ {
+ g_object_set(G_OBJECT(station->tabs),
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ g_object_set(G_OBJECT(station->toolbar),
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 1,
+ "row", 0,
+ "column-span", 1,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack));
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 2,
+ "row", 0,
+ "column-span", 1,
+ NULL);
+
+ gtk_widget_set_visible(station->sep2, TRUE);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep2);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 3,
+ "row", 0,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 4,
+ "row", 0,
+ NULL);
+
+ }
+
+ g_object_notify_by_pspec(object, pspec);
+
+ }
+
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkDockStation *station; /* Version spécialisée */
+
+ station = GTK_DOCK_STATION(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum(value, station->orientation);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "easygtk.h"
+#include "../core/params.h"
+#include "../common/extstr.h"
+#include "../glibext/chrysamarshal.h"
+
+
+
+/* Procède à l'initialisation de l'afficheur concentré. */
+static void gtk_dock_station_class_init(GtkDockStationClass *);
+
+/* Procède à l'initialisation du support d'affichage concentré. */
+static void gtk_dock_station_init(GtkDockStation *);
+
+/* Met à jour le titre du support de panneaux concentrés. */
+static gboolean gtk_dock_station_switch_panel(GtkNotebook *, gpointer *, guint, GtkDockStation *);
+
+
+
+
+/* Révèle ou cache la zone de recherches. */
+static void on_toggle_revealer(GtkToggleButton *, GtkDockStation *);
+
+/* Demande l'apparition d'un menu pour inclure des composants. */
+static void on_click_for_menu(GtkButton *, GtkDockStation *);
+
+/* Demande la disparition du composant courant. */
+static void on_click_for_close(GtkButton *, GtkDockStation *);
+
+
+
+
+
+
+/* Détermine le type du composant d'affichage concentré. */
+G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_NOTEBOOK)
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_class_init(GtkDockStationClass *class)
+{
+ g_signal_new("dock-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, dock_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("undock-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, undock_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("switch-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, switch_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("menu-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, menu_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("close-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, close_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation du support d'affichage concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_init(GtkDockStation *station)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ GtkWidget *hbox; /* Division supérieure */
+ GtkWidget *button; /* Bouton de contrôle */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ gtk_notebook_set_show_border(notebook, FALSE);
+ gtk_notebook_set_scrollable(notebook, TRUE);
+
+ /* Définition de la zone de contrôle */
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_valign(hbox, GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(hbox, 8);
+ gtk_widget_show(hbox);
+
+ button = qck_create_toggle_button_with_named_img(G_OBJECT(station), "search",
+ "edit-find-symbolic", GTK_ICON_SIZE_MENU, NULL,
+ G_CALLBACK(on_toggle_revealer), station);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ button = qck_create_button_with_named_img(G_OBJECT(station), "menu",
+ "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL,
+ G_CALLBACK(on_click_for_menu), station);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ button = qck_create_button_with_named_img(G_OBJECT(station), "close",
+ "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL,
+ G_CALLBACK(on_click_for_close), station);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END);
+
+ g_signal_connect(notebook, "switch-page",
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau composant pour support d'affichage concentré.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_dock_station_new(void)
+{
+ return g_object_new(GTK_TYPE_DOCK_STATION, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : notebook = support à l'origine de la mise à jour. *
+* page = onglet mis en avant. *
+* index = indice de l'onglet actuellement actif. *
+* station = conteneur de gestion supérieur. *
+* *
+* Description : Met à jour le titre du support de panneaux concentrés. *
+* *
+* Retour : TRUE ? *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_dock_station_switch_panel(GtkNotebook *notebook, gpointer *page, guint index, GtkDockStation *station)
+{
+ GtkWidget *widget; /* Panneau concerné */
+ GtkDockable *dockable; /* Elément encapsulé */
+ GtkWidget *button; /* Bouton de contrôle */
+
+ widget = gtk_notebook_get_nth_page(notebook, index);
+
+ dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
+
+ /* Mise à jour des boutons utilisables */
+
+ button = GTK_WIDGET(g_object_get_data(G_OBJECT(station), "search"));
+
+ if (gtk_dockable_can_search(dockable))
+ gtk_widget_show(button);
+ else
+ gtk_widget_hide(button);
+
+ /* Remontée du changement d'onglet */
+
+ g_signal_emit_by_name(station, "switch-widget", widget);
+
+ return TRUE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK à compléter. *
+* dockable = nouvel élément à intégrer. *
+* *
+* Description : Ajoute un paquet d'informations à l'affichage centralisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#include "gtkdisplaypanel.h"
+#include "../gui/panels/history.h"
+void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockable)
+{
+ GtkWidget *widget; /* Composant GTK à intégrer */
+ char *name; /* Nom à donner à l'onglet */
+ char *desc; /* Description à y associer */
+ int max; /* Taille maximale des titres */
+ GtkWidget *label; /* Etiquette d'onglet */
+ GtkNotebook *notebook; /* Autre version du composant */
+
+
+
+
+
+
+
+ /* Récupération des éléments utiles */
+
+ widget = gtk_dockable_build_widget(dockable);
+
+ //widget = gtk_button_new_with_label("123");
+ gtk_widget_show(widget);
+
+
+ g_object_set_data(G_OBJECT(widget), "dockable", dockable);
+
+ name = gtk_dockable_get_name(dockable);
+ desc = gtk_dockable_get_desc(dockable);
+
+ /* Mise en place de la page */
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_ELLIPSIS_TAB, &max))
+ max = -1;
+
+ name = ellipsis(name, max);
+ label = qck_create_label(NULL, NULL, name);
+ free(name);
+
+ notebook = GTK_NOTEBOOK(station);
+
+ if (gtk_notebook_get_n_pages(notebook) > 0)
+ g_signal_handlers_disconnect_by_func(notebook,
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+ gtk_notebook_append_page(notebook, widget, label);
+
+ gtk_widget_set_tooltip_text(label, desc);
+
+ free(desc);
+
+ if (gtk_notebook_get_n_pages(notebook) > 1)
+ g_signal_connect(notebook, "switch-page",
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+ /* Lancement des mises à jour */
+
+ if (gtk_notebook_get_n_pages(notebook) > 1)
+ gtk_notebook_set_current_page(notebook, -1);
+
+ //g_signal_emit_by_name(station, "dock-widget", widget);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK à compléter. *
+* widget = nouvel élément à intégrer. *
+* *
+* Description : Change le contenu de l'onglet courant uniquement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *widget)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ gint index; /* Indice de l'onglet actif */
+ GtkWidget *old; /* Ancien composant */
+ GtkWidget *label; /* Etiquette d'onglet */
+ char *str; /* Titre des prochaines fois */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ index = gtk_notebook_get_current_page(notebook);
+
+ g_signal_handlers_disconnect_by_func(notebook,
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+ old = gtk_notebook_get_nth_page(notebook, index);
+ label = gtk_notebook_get_tab_label(notebook, old);
+
+ g_object_ref(G_OBJECT(label));
+ str = g_object_get_data(G_OBJECT(old), "title");
+
+ gtk_notebook_remove_page(notebook, index);
+ gtk_notebook_insert_page(notebook, widget, label, index);
+
+ g_object_unref(G_OBJECT(label));
+ g_object_set_data(G_OBJECT(widget), "title", str);
+
+ gtk_notebook_set_current_page(notebook, index);
+
+ g_signal_connect(notebook, "switch-page",
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK à compléter. *
+* dockable = élément existant à retirer. *
+* *
+* Description : Retire un paquet d'informations de l'affichage centralisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_remove_dockable(GtkDockStation *station, GtkDockable *dockable)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ GtkWidget *widget; /* Composant GTK à retirer */
+ gint index; /* Indice de l'onglet visé */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ widget = gtk_dockable_decompose(dockable, NULL);
+
+ index = gtk_notebook_page_num(notebook, widget);
+
+ gtk_notebook_remove_page(notebook, index);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* station = station d'accueil pour différents composants. *
+* *
+* Description : Révèle ou cache la zone de recherches. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_toggle_revealer(GtkToggleButton *button, GtkDockStation *station)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ gint index; /* Indice de l'onglet courant */
+ GtkWidget *widget; /* Panneau concerné */
+ GtkDockable *dockable; /* Elément encapsulé */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ index = gtk_notebook_get_current_page(notebook);
+ widget = gtk_notebook_get_nth_page(notebook, index);
+
+ dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
+
+ gtk_dockable_toggle_revealer(dockable, widget, gtk_toggle_button_get_active(button));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* station = station d'accueil pour différents composants. *
+* *
+* Description : Demande l'apparition d'un menu pour inclure des composants. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_click_for_menu(GtkButton *button, GtkDockStation *station)
+{
+ g_signal_emit_by_name(station, "menu-requested", button);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* station = station d'accueil pour différents composants. *
+* *
+* Description : Demande la disparition du composant courant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_click_for_close(GtkButton *button, GtkDockStation *station)
+{
+ g_signal_emit_by_name(station, "close-requested", button);
+
+}
+
+
+#endif
+
diff --git a/src/gtkext/gtkdockstation.h b/src/gtkext/dockstation.h
index f286c1c..e4c849f 100644
--- a/src/gtkext/gtkdockstation.h
+++ b/src/gtkext/dockstation.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkdockstation.h - prototypes pour la manipulation et l'affichage de composants rassemblés
+ * dockstation.h - prototypes pour la manipulation et l'affichage de composants rassemblés
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,13 +21,46 @@
*/
-#ifndef _GTKEXT_GTKDOCKSTATION_H
-#define _GTKEXT_GTKDOCKSTATION_H
+#ifndef _GTKEXT_DOCKSTATION_H
+#define _GTKEXT_DOCKSTATION_H
#include <gtk/gtk.h>
+#include "panel.h"
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_DOCK_STATION (gtk_dock_station_get_type())
+
+DECLARE_GTYPE(GtkDockStation, gtk_dock_station, GTK, DOCK_STATION);
+
+
+/* Crée un nouveau composant pour support d'affichage concentré. */
+GtkWidget *gtk_dock_station_new(void);
+
+/* Ajoute un panneau à un groupe de tuiles. */
+void gtk_dock_station_add_panel(GtkDockStation *, GtkTiledPanel *);
+
+/* Ajoute un panneau à conserver à un groupe de tuiles. */
+void gtk_dock_station_keep_panel(GtkDockStation *, GtkTiledPanel *);
+
+/* Indique si la station d'accueil contient au moins un panneau. */
+bool gtk_dock_station_is_empty(const GtkDockStation *);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_dock_station_notify_new_main_panel_state(const GtkDockStation *, GtkTiledPanel *, bool);
+
+
+
+
+#if 0
+
+#include <gtk/gtk.h>
+
+
#include "gtkdockable.h"
@@ -76,9 +109,6 @@ struct _GtkDockStationClass
/* Détermine le type du composant d'affichage concentré. */
GType gtk_dock_station_get_type(void);
-/* Crée un nouveau composant pour support d'affichage concentré. */
-GtkWidget *gtk_dock_station_new(void);
-
/* Ajoute un paquet d'informations à l'affichage centralisé. */
void gtk_dock_station_add_dockable(GtkDockStation *, GtkDockable *);
@@ -92,6 +122,7 @@ void gtk_dock_station_remove_dockable(GtkDockStation *, GtkDockable *);
//G_END_DECLS
+#endif
-#endif /* _GTKEXT_GTKDOCKSTATION_H */
+#endif /* _GTKEXT_DOCKSTATION_H */
diff --git a/src/gtkext/dockstation.ui b/src/gtkext/dockstation.ui
new file mode 100644
index 0000000..4d25134
--- /dev/null
+++ b/src/gtkext/dockstation.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkDockStation" parent="GtkGrid">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkStackSwitcher" id="tabs">
+ <property name="orientation">horizontal</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="margin-start">2</property>
+ <property name="margin-top">2</property>
+ <property name="margin-end">2</property>
+ <property name="margin-bottom">2</property>
+ <property name="stack">stack</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="toolbar">
+ <property name="orientation">horizontal</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">window-close-symbolic</property>
+ <style>
+ <class name="circular"/>
+ <class name="flat"/>
+ <class name="control-button"/>
+ </style>
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">4</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="sep1">
+ <property name="orientation">horizontal</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">true</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="sep2">
+ <property name="orientation">horizontal</property>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/gresource.xml b/src/gtkext/gresource.xml
index 225b2a4..26943a6 100644
--- a/src/gtkext/gresource.xml
+++ b/src/gtkext/gresource.xml
@@ -1,7 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/re/chrysalide/framework/gtkext">
+ <file compressed="true">dockstation.ui</file>
+ <file compressed="true">grid.ui</file>
<file compressed="true">hexview.css</file>
<file compressed="true">hexview.ui</file>
+ <file compressed="true">launcher.ui</file>
+ <file compressed="true">statusstack.ui</file>
+ <file compressed="true">tweak.ui</file>
+ </gresource>
+ <gresource prefix="/re/chrysalide/framework/gui/icons/scalable/actions">
+ <file compressed="true" alias="nolock-symbolic.svg">../../data/images/nolock-symbolic.svg</file>
+ <file compressed="true" alias="locked-symbolic.svg">../../data/images/locked-symbolic.svg</file>
+ <file compressed="true" alias="unlocked-symbolic.svg">../../data/images/unlocked-symbolic.svg</file>
</gresource>
</gresources>
diff --git a/src/gtkext/grid-int.h b/src/gtkext/grid-int.h
new file mode 100644
index 0000000..8a2702b
--- /dev/null
+++ b/src/gtkext/grid-int.h
@@ -0,0 +1,81 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * grid-int.h - prototypes interne pour un composant d'affichage avec des chemins vers les composants contenus
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRID_INT_H
+#define _GTKEXT_GRID_INT_H
+
+
+#include "dockstation.h"
+#include "grid.h"
+
+
+
+/* Conteneur pour un affichage en tuiles nommées (instance) */
+struct _GtkTilingGrid
+{
+ GtkGrid parent; /* A laisser en premier */
+
+ GSettings *settings; /* Configuration du conteneur */
+
+ LayoutReachOptions layout; /* Disposition générale */
+
+ bool visible[TGB_COUNT]; /* Visibilités souhaitées */
+
+ GtkRevealer *top; /* Zone d'accueil #1 */
+ GtkWidget *top_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *top_station; /* Station entière */
+
+ GtkRevealer *left; /* Zone d'accueil #2 */
+ GtkWidget *left_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *left_station; /* Station entière */
+
+ GtkDockStation *main_station; /* Zone d'accueil #3 */
+
+ GtkRevealer *right; /* Zone d'accueil #4 */
+ GtkWidget *right_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *right_station; /* Station entière */
+
+ GtkRevealer *bottom; /* Zone d'accueil #5 */
+ GtkWidget *bottom_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *bottom_station; /* Station entière */
+
+ GtkGesture *tpad_gesture[TGB_COUNT]; /* Gestionnaires du touchpad */
+
+ bool panning; /* Redimensionnement en cours */
+
+};
+
+/* Conteneur pour un affichage en tuiles nommées (classe) */
+struct _GtkTilingGridClass
+{
+ GtkGridClass parent; /* A laisser en premier */
+
+ /* Signaux */
+
+ void (* station_created) (GtkTilingGrid *, GtkDockStation *, gpointer);
+
+};
+
+
+
+#endif /* _GTKEXT_GRID_INT_H */
diff --git a/src/gtkext/grid.c b/src/gtkext/grid.c
new file mode 100644
index 0000000..eb3cdf9
--- /dev/null
+++ b/src/gtkext/grid.c
@@ -0,0 +1,1128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * grid.c - composant d'affichage avec des chemins vers les composants contenus
+ *
+ * Copyright (C) 2018-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "grid.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "grid-int.h"
+#include "helpers.h"
+#include "bindings/grid-enums.h"
+
+
+
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _TilingGridProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_LAYOUT, /* Disposition générale */
+
+ PROP_EMPTY_TOP, /* Vide de la zone supérieure */
+ PROP_EMPTY_LEFT, /* Vide de la zone de gauche */
+ PROP_EMPTY_RIGHT, /* Vide de la zone de droite */
+ PROP_EMPTY_BOTTOM, /* Vide de la zone inférieure */
+
+ PROP_VISIBLE_TOP, /* Visibilité de zone sup. */
+ PROP_VISIBLE_LEFT, /* Visibilité de zone de gauche*/
+ PROP_VISIBLE_RIGHT, /* Visibilité de zone de droite*/
+ PROP_VISIBLE_BOTTOM, /* Visibilité de zone inf. */
+
+ N_PROPERTIES
+
+} TilingGridProperty;
+
+static GParamSpec *_tiling_grid_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des conteneurs d'affichage en tuiles. */
+static void gtk_tiling_grid_class_init(GtkTilingGridClass *);
+
+/* Initialise une instance de conteneur d'affichage en tuiles. */
+static void gtk_tiling_grid_init(GtkTilingGrid *);
+
+/* Supprime toutes les références externes. */
+static void gtk_tiling_grid_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_tiling_grid_finalize(GObject *);
+
+/* Réagit à une intégration ou à un retrait de panneau. */
+static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *, GtkTiledPanel *, GtkTilingGrid *);
+
+
+
+/* -------------------- REDIMENSIONNEMENT DE ZONES POUR PANNEAUX -------------------- */
+
+
+/* Initie un redimensionnement par drag-and-drop. */
+static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Applique l'effet d'un redimensionnement drag-and-drop donné. */
+static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *, TilingGridBorder, double, double);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Clôture un drag-and-drop de redimensionnement. */
+static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_tiling_grid_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_tiling_grid_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE DU COMPOSANT GTK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du conteneur d'affichage en tuiles nommées. */
+G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_GRID)
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des conteneurs d'affichage en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_class_init(GtkTilingGridClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_tiling_grid_dispose;
+ object->finalize = gtk_tiling_grid_finalize;
+ object->set_property = gtk_tiling_grid_set_property;
+ object->get_property = gtk_tiling_grid_get_property;
+
+ _tiling_grid_properties[PROP_LAYOUT] =
+ g_param_spec_flags("layout", NULL, NULL,
+ LAYOUT_REACH_OPTIONS_TYPE,
+ LRO_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_TOP] =
+ g_param_spec_boolean("empty-top", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_LEFT] =
+ g_param_spec_boolean("empty-left", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_RIGHT] =
+ g_param_spec_boolean("empty-right", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_BOTTOM] =
+ g_param_spec_boolean("empty-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * La valeur initiale des champs suivants est à maintenir synchronisée avec
+ * les initialisations de gtk_tiling_grid_init().
+ */
+
+ _tiling_grid_properties[PROP_VISIBLE_TOP] =
+ g_param_spec_boolean("visible-top", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_LEFT] =
+ g_param_spec_boolean("visible-left", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_RIGHT] =
+ g_param_spec_boolean("visible-right", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_BOTTOM] =
+ g_param_spec_boolean("visible-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _tiling_grid_properties);
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ g_type_ensure(GTK_TYPE_DOCK_STATION);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/grid.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_panel_un_docked));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_begin));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_top_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_left_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_right_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_bottom_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_end));
+
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, main_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_station);
+
+
+ /////////////
+
+ g_signal_new("station-created",
+ GTK_TYPE_TILING_GRID,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkTilingGridClass, station_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET/*DOCK_STATION FIXME */);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = instance GTK à initialiser. *
+* *
+* Description : Initialise une instance de conteneur d'affichage en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_init(GtkTilingGrid *grid)
+{
+ gtk_widget_init_template(GTK_WIDGET(grid));
+
+ grid->settings = g_settings_new_with_path("re.chrysalide.framework.tiledgrid",
+ "/re/chrysalide/framework/gui/tiles/");
+
+ g_settings_bind(grid->settings, "layout",
+ grid, "layout",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /**
+ * L'initialisation des champs suivants est à maintenir synchronisée avec
+ * les valeurs initiales de gtk_tiling_grid_class_init().
+ */
+
+ grid->visible[TGB_TOP] = true;
+ grid->visible[TGB_LEFT] = true;
+ grid->visible[TGB_RIGHT] = true;
+ grid->visible[TGB_BOTTOM] = true;
+
+ g_settings_bind(grid->settings, "top-request",
+ grid->top_station, "height-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "top-visibility",
+ grid, "visible-top",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "left-request",
+ grid->left_station, "width-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "left-visibility",
+ grid, "visible-left",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "right-request",
+ grid->right_station, "width-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "right-visibility",
+ grid, "visible-right",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "bottom-request",
+ grid->bottom_station, "height-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "bottom-visibility",
+ grid, "visible-bottom",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_widget_set_cursor_from_name(grid->top_handle, "row-resize");
+ gtk_widget_set_cursor_from_name(grid->left_handle, "col-resize");
+ gtk_widget_set_cursor_from_name(grid->right_handle, "col-resize");
+ gtk_widget_set_cursor_from_name(grid->bottom_handle, "row-resize");
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_dispose(GObject *object)
+{
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION);
+
+ grid = GTK_TILING_GRID(object);
+
+ g_clear_object(&grid->settings);
+
+ G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une nouvelle instance de conteneur avec tuiles. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_tiling_grid_new(void)
+{
+ GtkWidget *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_TILING_GRID, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* visible = nouveau statut de visibilité à appliquer. *
+* *
+* Description : Affiche ou masque une zone du conteneur en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiling_grid_set_visible(GtkTilingGrid *grid, TilingGridBorder border, bool visible)
+{
+ GtkRevealer *revealer; /* Cible visée par l'opération */
+ GtkDockStation *station; /* Apport d'une contrainte */
+
+ if (grid->visible[border] != visible)
+ {
+ grid->visible[border] = visible;
+
+ switch (border)
+ {
+ case TGB_TOP:
+ revealer = grid->top;
+ station = grid->top_station;
+ break;
+
+ case TGB_LEFT:
+ revealer = grid->left;
+ station = grid->left_station;
+ break;
+
+ case TGB_RIGHT:
+ revealer = grid->right;
+ station = grid->right_station;
+ break;
+
+ case TGB_BOTTOM:
+ revealer = grid->bottom;
+ station = grid->bottom_station;
+ break;
+
+ }
+
+ gtk_revealer_set_reveal_child(revealer, visible && !gtk_dock_station_is_empty(station));
+
+ g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_VISIBLE_TOP + border]);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* *
+* Description : Fournit la visibilité d'une zone du conteneur en tuiles. *
+* *
+* Retour : Visibilité de la zone considérée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_tiling_grid_get_visible(GtkTilingGrid *grid, TilingGridBorder border)
+{
+ bool result; /* Statut à retourner */
+
+ result = grid->visible[border];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* panel = nouveau panneau à afficher. *
+* keep = indique si le panneau est à conserver présent. *
+* *
+* Description : Ajoute un panneau à un conteneur en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiling_grid_add_panel(GtkTilingGrid *grid, GtkTiledPanel *panel, bool keep)
+{
+ char *path; /* Chemin visé par le panneau */
+ bool static_path; /* Nature du chemin à traiter */
+
+ path = gtk_tiled_panel_get_path(panel);
+
+ static_path = (path == NULL);
+
+ if (static_path)
+ path = "";
+
+ switch (path[0])
+ {
+ case 'N':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->top_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->top_station, panel);
+ break;
+
+ case 'W':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->left_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->left_station, panel);
+ break;
+
+ case '\0':
+ case 'M':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->main_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->main_station, panel);
+ break;
+
+ case 'E':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->right_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->right_station, panel);
+ break;
+
+ case 'S':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->bottom_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->bottom_station, panel);
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (!static_path)
+ free(path);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *grid, GtkTiledPanel *main, bool activated)
+{
+ gtk_dock_station_notify_new_main_panel_state(grid->top_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->left_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->main_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->right_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->bottom_station, main, activated);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK ayant connu un changement. *
+* widget = nouvel élément à intégrer. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Réagit à une intégration ou à un retrait de panneau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *station, GtkTiledPanel *panel, GtkTilingGrid *grid)
+{
+ TilingGridBorder border; /* Aire concernée par l'action */
+ GtkRevealer *revealer; /* Cible visée par l'opération */
+ bool new_state; /* Nouveau statut d'affichage */
+
+ if (station == grid->top_station)
+ {
+ border = TGB_TOP;
+ revealer = grid->top;
+ }
+
+ else if (station == grid->left_station)
+ {
+ border = TGB_LEFT;
+ revealer = grid->left;
+ }
+
+ else if (station == grid->right_station)
+ {
+ border = TGB_RIGHT;
+ revealer = grid->right;
+ }
+
+ else if (station == grid->bottom_station)
+ {
+ border = TGB_BOTTOM;
+ revealer = grid->bottom;
+ }
+
+ else
+ assert(false);
+
+ new_state = grid->visible[border] && !gtk_dock_station_is_empty(station);
+
+ if (gtk_revealer_get_reveal_child(revealer) != new_state)
+ gtk_revealer_set_reveal_child(revealer, new_state);
+
+ /**
+ * On ne sait pas si l'état a réellement changé, mais on avertit
+ * d'une mise à jour quand même, au cas où.
+ */
+
+ g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_EMPTY_TOP + border]);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* REDIMENSIONNEMENT DE ZONES POUR PANNEAUX */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* start_x = pointe de départ sur l'axe des abscisses. *
+* start_y = pointe de départ sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Initie un redimensionnement par drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *gesture, double start_x, double start_y, GtkTilingGrid *grid)
+{
+ gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+
+ grid->panning = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* *
+* Description : Applique l'effet d'un redimensionnement drag-and-drop donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *grid, TilingGridBorder border, double offset_x, double offset_y)
+{
+ GtkDockStation *station; /* Station entière */
+ int request; /* Taille requise */
+
+ /* Sélection de la poignée adaptée */
+
+ switch (border)
+ {
+ case TGB_TOP:
+ station = grid->top_station;
+ break;
+
+ case TGB_LEFT:
+ station = grid->left_station;
+ break;
+
+ case TGB_RIGHT:
+ station = grid->right_station;
+ break;
+
+ case TGB_BOTTOM:
+ station = grid->bottom_station;
+ break;
+
+ }
+
+ /* Détermination d'une nouvelle position et application */
+
+ switch (border)
+ {
+ case TGB_TOP:
+ case TGB_BOTTOM:
+ g_object_get(G_OBJECT(station), "height-request", &request, NULL);
+ break;
+
+ case TGB_LEFT:
+ case TGB_RIGHT:
+ g_object_get(G_OBJECT(station), "width-request", &request, NULL);
+ break;
+
+ }
+
+ switch (border)
+ {
+ case TGB_TOP:
+ request += offset_y;
+ break;
+
+ case TGB_LEFT:
+ request += offset_x;
+ break;
+
+ case TGB_RIGHT:
+ request += -offset_x;
+ break;
+
+ case TGB_BOTTOM:
+ request += -offset_y;
+ break;
+
+ }
+
+ if (request > 0)
+ {
+ switch (border)
+ {
+ case TGB_TOP:
+ case TGB_BOTTOM:
+ g_object_set(G_OBJECT(station), "height-request", request, NULL);
+ break;
+
+ case TGB_LEFT:
+ case TGB_RIGHT:
+ g_object_set(G_OBJECT(station), "width-request", request, NULL);
+ break;
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_TOP, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_LEFT, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_RIGHT, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_BOTTOM, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement final sur l'axe des abscisses. *
+* offset_y = déplacement final sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Clôture un drag-and-drop de redimensionnement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ if (!grid->panning)
+ gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_DENIED);
+ else
+ grid->panning = false;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ grid = GTK_TILING_GRID(object);
+
+ switch (prop_id)
+ {
+ case PROP_LAYOUT:
+ if (grid->layout != g_value_get_flags(value))
+ {
+ grid->layout = g_value_get_flags(value);
+
+ apply_tiling_grid_layout(GTK_GRID(grid), grid->layout, (GtkWidget *[]) {
+ GTK_WIDGET(grid->top), GTK_WIDGET(grid->left),
+ GTK_WIDGET(grid->right), GTK_WIDGET(grid->bottom)
+ });
+
+ g_object_notify_by_pspec(object, pspec);
+
+ }
+ break;
+
+ gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_TOP:
+ gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_LEFT:
+ gtk_tiling_grid_set_visible(grid, TGB_LEFT, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_RIGHT:
+ gtk_tiling_grid_set_visible(grid, TGB_RIGHT, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_BOTTOM:
+ gtk_tiling_grid_set_visible(grid, TGB_BOTTOM, g_value_get_boolean(value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ grid = GTK_TILING_GRID(object);
+
+ switch (prop_id)
+ {
+ case PROP_EMPTY_TOP:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->top_station));
+ break;
+
+ case PROP_EMPTY_LEFT:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->left_station));
+ break;
+
+ case PROP_EMPTY_RIGHT:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->right_station));
+ break;
+
+ case PROP_EMPTY_BOTTOM:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->bottom_station));
+ break;
+
+ case PROP_VISIBLE_TOP:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_TOP));
+ break;
+
+ case PROP_VISIBLE_LEFT:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_LEFT));
+ break;
+
+ case PROP_VISIBLE_RIGHT:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_RIGHT));
+ break;
+
+ case PROP_VISIBLE_BOTTOM:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_BOTTOM));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* FORME GENERIQUE DE MISE EN DISPOSITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = composant GTK dont le contenu est à arranger. *
+* options = options de mise en place. *
+* panels = liste organisée de composants à déplacer. *
+* *
+* Description : Met en place une disposition particulière de panneaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void apply_tiling_grid_layout(GtkGrid *grid, LayoutReachOptions options, GtkWidget *panels[TGB_COUNT])
+{
+ int top_panel_span; /* Etendue d'un composant #1 */
+ int left_panel_span; /* Etendue d'un composant #2 */
+ int right_panel_span; /* Etendue d'un composant #3 */
+ int bottom_panel_span; /* Etendue d'un composant #4 */
+ int top_panel_column; /* Position de composant #1 */
+ int left_panel_row; /* Position de composant #2 */
+ int right_panel_row; /* Position de composant #3 */
+ int bottom_panel_column; /* Position de composant #4 */
+ GtkLayoutManager *layout; /* Gestionnaire de disposition */
+ GtkGridLayoutChild *top_panel_layout; /* Disposition de composant #1 */
+ GtkGridLayoutChild *left_panel_layout; /* Disposition de composant #2 */
+ GtkGridLayoutChild *right_panel_layout; /* Disposition de composant #3 */
+ GtkGridLayoutChild *bottom_panel_layout;/* Disposition de composant #4 */
+
+ /* Calcul des placements */
+
+ top_panel_span = 3;
+ left_panel_span = 3;
+ right_panel_span = 3;
+ bottom_panel_span = 3;
+
+ if (options & LRO_LEFT_TOP_REACH)
+ {
+ top_panel_column = 1;
+ top_panel_span--;
+ left_panel_row = 0;
+ }
+ else
+ {
+ top_panel_column = 0;
+ left_panel_row = 1;
+ left_panel_span--;
+ }
+
+ if (options & LRO_LEFT_BOTTOM_REACH)
+ {
+ bottom_panel_column = 1;
+ bottom_panel_span--;
+ }
+ else
+ {
+ left_panel_span--;
+ bottom_panel_column = 0;
+ }
+
+ if (options & LRO_RIGHT_TOP_REACH)
+ {
+ top_panel_span--;
+ right_panel_row = 0;
+ }
+ else
+ {
+ right_panel_row = 1;
+ right_panel_span--;
+ }
+
+ if (options & LRO_RIGHT_BOTTOM_REACH)
+ bottom_panel_span--;
+ else
+ right_panel_span--;
+
+ /* Mise en application des contraintes */
+
+ layout = gtk_widget_get_layout_manager(GTK_WIDGET(grid));
+
+ top_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_TOP]));
+ left_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_LEFT]));
+ right_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_RIGHT]));
+ bottom_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_BOTTOM]));
+
+ g_object_set(G_OBJECT(top_panel_layout),
+ "column", top_panel_column,
+ "column-span", top_panel_span,
+ NULL);
+
+ g_object_set(G_OBJECT(left_panel_layout),
+ "row", left_panel_row,
+ "row-span", left_panel_span,
+ NULL);
+
+ g_object_set(G_OBJECT(right_panel_layout),
+ "row", right_panel_row,
+ "row-span", right_panel_span,
+ NULL);
+
+ g_object_set(G_OBJECT(bottom_panel_layout),
+ "column", bottom_panel_column,
+ "column-span", bottom_panel_span,
+ NULL);
+
+ gtk_layout_manager_layout_changed(layout);
+
+}
diff --git a/src/gtkext/tiledgrid.h b/src/gtkext/grid.h
index 539e248..fd98035 100644
--- a/src/gtkext/tiledgrid.h
+++ b/src/gtkext/grid.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* tiledgrid.h - prototypes pour un composant d'affichage avec des chemins vers les composants contenus
*
- * Copyright (C) 2018-2019 Cyrille Bagard
+ * Copyright (C) 2018-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,10 +21,81 @@
*/
-#ifndef _GTKEXT_TILEDGRID_H
-#define _GTKEXT_TILEDGRID_H
+#ifndef _GTKEXT_GRID_H
+#define _GTKEXT_GRID_H
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+
+#include "panel.h"
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_TILING_GRID (gtk_tiling_grid_get_type())
+
+DECLARE_GTYPE(GtkTilingGrid, gtk_tiling_grid, GTK, TILING_GRID);
+
+
+/* Crée une nouvelle instance de conteneur avec tuiles. */
+GtkWidget *gtk_tiling_grid_new(void);
+
+/* Liste des zones de bordure */
+typedef enum _TilingGridBorder /*< skip (glib-mkenums) >*/
+{
+ TGB_TOP, /* Zone supérieure */
+ TGB_LEFT, /* Zone de gauche */
+ TGB_RIGHT, /* Zone de droite */
+ TGB_BOTTOM, /* Zone inférieure */
+
+} TilingGridBorder;
+
+/**
+ * Fixe le nombre de combinaisons sans le rendre visible dans l'énumération.
+ */
+#define TGB_COUNT (TGB_BOTTOM + 1)
+
+/* Affiche ou masque une zone du conteneur en tuiles. */
+void gtk_tiling_grid_set_visible(GtkTilingGrid *, TilingGridBorder, bool);
+
+/* Fournit la visibilité d'une zone du conteneur en tuiles. */
+bool gtk_tiling_grid_get_visible(GtkTilingGrid *, TilingGridBorder);
+
+/* Ajoute un panneau à un conteneur en tuiles. */
+void gtk_tiling_grid_add_panel(GtkTilingGrid *, GtkTiledPanel *, bool);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *, GtkTiledPanel *, bool);
+
+
+
+/* --------------------- FORME GENERIQUE DE MISE EN DISPOSITION --------------------- */
+
+
+/* Options de dispositions cumulables */
+typedef enum _LayoutReachOptions /*< flags (glib-mkenums) >*/
+{
+ LRO_NONE = (0 << 0), /* Aucune atteinte des bords */
+ LRO_LEFT_TOP_REACH = (1 << 0), /* Atteinte du bord haut à G. */
+ LRO_LEFT_BOTTOM_REACH = (1 << 1), /* Atteinte du bord bas à G. */
+ LRO_RIGHT_TOP_REACH = (1 << 2), /* Atteinte du bord haut à D. */
+ LRO_RIGHT_BOTTOM_REACH = (1 << 3), /* Atteinte du bord bas à D. */
+
+} LayoutReachOptions;
+
+/* Met en place une disposition particulière de panneaux. */
+void apply_tiling_grid_layout(GtkGrid *, LayoutReachOptions, GtkWidget *[TGB_COUNT]);
+
+
+
+
+
+
+
+#if 0
+
#include <gtk/gtk.h>
@@ -81,5 +152,7 @@ void gtk_tiled_grid_restore_positions(const GtkTiledGrid *, GGenConfig *);
void gtk_tiled_grid_save_positions(const GtkTiledGrid *, GGenConfig *);
+#endif
+
-#endif /* _GTKEXT_TILEDGRID_H */
+#endif /* _GTKEXT_GRID_H */
diff --git a/src/gtkext/grid.ui b/src/gtkext/grid.ui
new file mode 100644
index 0000000..b14ced2
--- /dev/null
+++ b/src/gtkext/grid.ui
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkTilingGrid" parent="GtkGrid">
+
+ <!-- Zone supérieure -->
+
+ <child>
+ <object class="GtkRevealer" id="top">
+ <property name="transition-type">slide-up</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkDockStation" id="top_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">30</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="top_handle">
+ <property name="orientation">vertical</property>
+ <property name="height-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_top_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone de gauche -->
+
+ <child>
+ <object class="GtkRevealer" id="left">
+ <property name="transition-type">slide-right</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkDockStation" id="left_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">300</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="left_handle">
+ <property name="orientation">horizontal</property>
+ <property name="width-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_left_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone centrale -->
+
+ <child>
+ <object class="GtkDockStation" id="main_station">
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone de droite -->
+
+ <child>
+ <object class="GtkRevealer" id="right">
+ <property name="transition-type">slide-left</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkSeparator" id="right_handle">
+ <property name="orientation">horizontal</property>
+ <property name="width-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_right_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkDockStation" id="right_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">300</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone inférieure -->
+
+ <child>
+ <object class="GtkRevealer" id="bottom">
+ <property name="transition-type">slide-up</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkSeparator" id="bottom_handle">
+ <property name="orientation">vertical</property>
+ <property name="height-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_bottom_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkDockStation" id="bottom_station">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">250</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/gtkdockstation.c b/src/gtkext/gtkdockstation.c
deleted file mode 100644
index 1757542..0000000
--- a/src/gtkext/gtkdockstation.c
+++ /dev/null
@@ -1,467 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkdockstation.c - manipulation et l'affichage de composants rassemblés
- *
- * Copyright (C) 2012-2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gtkdockstation.h"
-
-
-#include <malloc.h>
-#include <string.h>
-
-
-#include "easygtk.h"
-#include "../core/params.h"
-#include "../common/extstr.h"
-#include "../glibext/chrysamarshal.h"
-
-
-
-/* Procède à l'initialisation de l'afficheur concentré. */
-static void gtk_dock_station_class_init(GtkDockStationClass *);
-
-/* Procède à l'initialisation du support d'affichage concentré. */
-static void gtk_dock_station_init(GtkDockStation *);
-
-/* Met à jour le titre du support de panneaux concentrés. */
-static gboolean gtk_dock_station_switch_panel(GtkNotebook *, gpointer *, guint, GtkDockStation *);
-
-
-
-
-/* Révèle ou cache la zone de recherches. */
-static void on_toggle_revealer(GtkToggleButton *, GtkDockStation *);
-
-/* Demande l'apparition d'un menu pour inclure des composants. */
-static void on_click_for_menu(GtkButton *, GtkDockStation *);
-
-/* Demande la disparition du composant courant. */
-static void on_click_for_close(GtkButton *, GtkDockStation *);
-
-
-
-
-
-
-/* Détermine le type du composant d'affichage concentré. */
-G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_NOTEBOOK)
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'afficheur concentré. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_dock_station_class_init(GtkDockStationClass *class)
-{
- g_signal_new("dock-widget",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, dock_widget),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("undock-widget",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, undock_widget),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("switch-widget",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, switch_widget),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("menu-requested",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, menu_requested),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("close-requested",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, close_requested),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation du support d'affichage concentré. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_dock_station_init(GtkDockStation *station)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- GtkWidget *hbox; /* Division supérieure */
- GtkWidget *button; /* Bouton de contrôle */
-
- notebook = GTK_NOTEBOOK(station);
-
- gtk_notebook_set_show_border(notebook, FALSE);
- gtk_notebook_set_scrollable(notebook, TRUE);
-
- /* Définition de la zone de contrôle */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_valign(hbox, GTK_ALIGN_CENTER);
- gtk_widget_set_margin_end(hbox, 8);
- gtk_widget_show(hbox);
-
- button = qck_create_toggle_button_with_named_img(G_OBJECT(station), "search",
- "edit-find-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_toggle_revealer), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
- button = qck_create_button_with_named_img(G_OBJECT(station), "menu",
- "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_click_for_menu), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
- button = qck_create_button_with_named_img(G_OBJECT(station), "close",
- "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_click_for_close), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
- gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END);
-
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un nouveau composant pour support d'affichage concentré.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkWidget *gtk_dock_station_new(void)
-{
- return g_object_new(GTK_TYPE_DOCK_STATION, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : notebook = support à l'origine de la mise à jour. *
-* page = onglet mis en avant. *
-* index = indice de l'onglet actuellement actif. *
-* station = conteneur de gestion supérieur. *
-* *
-* Description : Met à jour le titre du support de panneaux concentrés. *
-* *
-* Retour : TRUE ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_dock_station_switch_panel(GtkNotebook *notebook, gpointer *page, guint index, GtkDockStation *station)
-{
- GtkWidget *widget; /* Panneau concerné */
- GtkDockable *dockable; /* Elément encapsulé */
- GtkWidget *button; /* Bouton de contrôle */
-
- widget = gtk_notebook_get_nth_page(notebook, index);
-
- dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
-
- /* Mise à jour des boutons utilisables */
-
- button = GTK_WIDGET(g_object_get_data(G_OBJECT(station), "search"));
-
- if (gtk_dockable_can_search(dockable))
- gtk_widget_show(button);
- else
- gtk_widget_hide(button);
-
- /* Remontée du changement d'onglet */
-
- g_signal_emit_by_name(station, "switch-widget", widget);
-
- return TRUE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = plateforme GTK à compléter. *
-* dockable = nouvel élément à intégrer. *
-* *
-* Description : Ajoute un paquet d'informations à l'affichage centralisé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-#include "gtkdisplaypanel.h"
-#include "../gui/panels/history.h"
-void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockable)
-{
- GtkWidget *widget; /* Composant GTK à intégrer */
- char *name; /* Nom à donner à l'onglet */
- char *desc; /* Description à y associer */
- int max; /* Taille maximale des titres */
- GtkWidget *label; /* Etiquette d'onglet */
- GtkNotebook *notebook; /* Autre version du composant */
-
-
-
-
-
-
-
- /* Récupération des éléments utiles */
-
- widget = gtk_dockable_build_widget(dockable);
-
- //widget = gtk_button_new_with_label("123");
- gtk_widget_show(widget);
-
-
- g_object_set_data(G_OBJECT(widget), "dockable", dockable);
-
- name = gtk_dockable_get_name(dockable);
- desc = gtk_dockable_get_desc(dockable);
-
- /* Mise en place de la page */
-
- if (!g_generic_config_get_value(get_main_configuration(), MPK_ELLIPSIS_TAB, &max))
- max = -1;
-
- name = ellipsis(name, max);
- label = qck_create_label(NULL, NULL, name);
- free(name);
-
- notebook = GTK_NOTEBOOK(station);
-
- if (gtk_notebook_get_n_pages(notebook) > 0)
- g_signal_handlers_disconnect_by_func(notebook,
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
- gtk_notebook_append_page(notebook, widget, label);
-
- gtk_widget_set_tooltip_text(label, desc);
-
- free(desc);
-
- if (gtk_notebook_get_n_pages(notebook) > 1)
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
- /* Lancement des mises à jour */
-
- if (gtk_notebook_get_n_pages(notebook) > 1)
- gtk_notebook_set_current_page(notebook, -1);
-
- //g_signal_emit_by_name(station, "dock-widget", widget);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = plateforme GTK à compléter. *
-* widget = nouvel élément à intégrer. *
-* *
-* Description : Change le contenu de l'onglet courant uniquement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *widget)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- gint index; /* Indice de l'onglet actif */
- GtkWidget *old; /* Ancien composant */
- GtkWidget *label; /* Etiquette d'onglet */
- char *str; /* Titre des prochaines fois */
-
- notebook = GTK_NOTEBOOK(station);
-
- index = gtk_notebook_get_current_page(notebook);
-
- g_signal_handlers_disconnect_by_func(notebook,
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
- old = gtk_notebook_get_nth_page(notebook, index);
- label = gtk_notebook_get_tab_label(notebook, old);
-
- g_object_ref(G_OBJECT(label));
- str = g_object_get_data(G_OBJECT(old), "title");
-
- gtk_notebook_remove_page(notebook, index);
- gtk_notebook_insert_page(notebook, widget, label, index);
-
- g_object_unref(G_OBJECT(label));
- g_object_set_data(G_OBJECT(widget), "title", str);
-
- gtk_notebook_set_current_page(notebook, index);
-
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = plateforme GTK à compléter. *
-* dockable = élément existant à retirer. *
-* *
-* Description : Retire un paquet d'informations de l'affichage centralisé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_dock_station_remove_dockable(GtkDockStation *station, GtkDockable *dockable)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- GtkWidget *widget; /* Composant GTK à retirer */
- gint index; /* Indice de l'onglet visé */
-
- notebook = GTK_NOTEBOOK(station);
-
- widget = gtk_dockable_decompose(dockable, NULL);
-
- index = gtk_notebook_page_num(notebook, widget);
-
- gtk_notebook_remove_page(notebook, index);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton à l'origine de la procédure. *
-* station = station d'accueil pour différents composants. *
-* *
-* Description : Révèle ou cache la zone de recherches. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_toggle_revealer(GtkToggleButton *button, GtkDockStation *station)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- gint index; /* Indice de l'onglet courant */
- GtkWidget *widget; /* Panneau concerné */
- GtkDockable *dockable; /* Elément encapsulé */
-
- notebook = GTK_NOTEBOOK(station);
-
- index = gtk_notebook_get_current_page(notebook);
- widget = gtk_notebook_get_nth_page(notebook, index);
-
- dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
-
- gtk_dockable_toggle_revealer(dockable, widget, gtk_toggle_button_get_active(button));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton à l'origine de la procédure. *
-* station = station d'accueil pour différents composants. *
-* *
-* Description : Demande l'apparition d'un menu pour inclure des composants. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_click_for_menu(GtkButton *button, GtkDockStation *station)
-{
- g_signal_emit_by_name(station, "menu-requested", button);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton à l'origine de la procédure. *
-* station = station d'accueil pour différents composants. *
-* *
-* Description : Demande la disparition du composant courant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_click_for_close(GtkButton *button, GtkDockStation *station)
-{
- g_signal_emit_by_name(station, "close-requested", button);
-
-}
diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c
deleted file mode 100644
index fe4e4d5..0000000
--- a/src/gtkext/gtkstatusstack.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkstatusstack.c - empilement d'informations de statut
- *
- * Copyright (C) 2015-2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gtkstatusstack.h"
-
-
-#include <assert.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include <i18n.h>
-
-
-#include "easygtk.h"
-#include "../gui/agroup.h"
-#include "../format/format.h"
-
-
-
-/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
-
-
-/* Navigation au sein d'assemblage */
-typedef struct _assembly_info assembly_info;
-
-/* Mémorisation des progressions */
-typedef struct _progress_info progress_info;
-
-
-/* Abstration d'une gestion de barre de statut (instance) */
-struct _GtkStatusStack
-{
- GtkBox parent; /* A laisser en premier */
-
- GtkStack *main; /* Pile d'informations associée*/
-
- GSourceFunc def_source; /* Appel en fin d'activité */
-
- GObject *asm_ref; /* Espace de référencements #1 */
- assembly_info *asm_info; /* Informations courantes #1 */
-
- GObject *prog_ref; /* Espace de référencements #2 */
- progress_info *prog_info; /* Informations courantes #2 */
-
-};
-
-/* Abstration d'une gestion de barre de statut (classe) */
-struct _GtkStatusStackClass
-{
- GtkBoxClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des barres de statut améliorées. */
-static void gtk_status_stack_class_init(GtkStatusStackClass *);
-
-/* Initialise une instance de barre de statut améliorée. */
-static void gtk_status_stack_init(GtkStatusStack *);
-
-/* Supprime toutes les références externes. */
-static void gtk_status_stack_dispose(GtkStatusStack *);
-
-/* Procède à la libération totale de la mémoire. */
-static void gtk_status_stack_finalize(GtkStatusStack *);
-
-
-
-/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
-
-
-/* Navigation au sein d'assemblage */
-struct _assembly_info
-{
- bool reset; /* Réinitialisation */
-
- mrange_t current; /* Emplacement correspondant */
-
- char *segment; /* Segment d'appartenance */
-
- VMPA_BUFFER(phys); /* Localisation physique */
- VMPA_BUFFER(virt); /* Localisation virtuelle */
-
- char *symbol; /* Eventuel symbole concerné */
-
- const char *encoding; /* Encodage de l'instruction */
- phys_t size; /* Taille de l'instruction */
-
-};
-
-
-/* Supprime l'empreinte mémoire d'informations d'assemblage. */
-static void reset_assembly_info(assembly_info *);
-
-/* Construit une barre d'état pour language d'assemblage. */
-static GtkWidget *build_assembly_status_stack(GtkStatusStack *);
-
-/* Réagit à un redimensionnement de la barre de désassemblage. */
-static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *);
-
-/* Réagit à un clic sur l'icône de zoom. */
-static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *);
-
-/* S'assure de l'affichage à jour de la partie "assemblage". */
-static gboolean gtk_status_stack_show_current_location(GtkStatusStack *);
-
-
-
-/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */
-
-
-/* Informations de progression */
-typedef struct _progress_status
-{
- activity_id_t id; /* Identifiant unique */
-
- char *message; /* Indication à faire valoir */
-
- unsigned long current; /* Position courante */
- unsigned long max; /* Couverture à parcourir */
-
- double last_updated; /* Dernière valeur poussée */
-
-} progress_status;
-
-/* Mémorisation des progressions */
-struct _progress_info
-{
- activity_id_t generator; /* Générateur de séquence */
-
- progress_status *statuses; /* Statuts de progression */
- size_t count; /* Nombre de ces statuts */
- GMutex access; /* Accès à la pile */
-
- guint tag; /* Identifiant de mise à jour */
-
-};
-
-
-#define PROGRESS_SIZE 200
-
-
-/* Supprime l'empreinte mémoire d'informations d'activité. */
-static void reset_progress_info(progress_info *);
-
-/* Construit une barre d'état pour un suivi d'activité. */
-static GtkWidget *build_progress_status_stack(GtkStatusStack *);
-
-/* S'assure de l'affichage à jour de la partie "activité". */
-static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION EXTERIEURE DE LA BARRE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type de la barre de statut améliorée. */
-G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX)
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe GTK à initialiser. *
-* *
-* Description : Initialise la classe des barres de statut améliorées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_class_init(GtkStatusStackClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = instance GTK à initialiser. *
-* *
-* Description : Initialise une instance de barre de statut améliorée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_init(GtkStatusStack *stack)
-{
- GtkWidget *layer; /* Couche à empiler */
-
- gtk_orientable_set_orientation(GTK_ORIENTABLE(stack), GTK_ORIENTATION_HORIZONTAL);
-
- stack->main = GTK_STACK(gtk_stack_new());
- gtk_widget_show(GTK_WIDGET(stack->main));
- gtk_box_pack_start(GTK_BOX(stack), GTK_WIDGET(stack->main), TRUE, TRUE, 8);
-
- stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location;
-
- layer = build_assembly_status_stack(stack);
- gtk_stack_add_named(stack->main, layer, "asm_info");
-
- stack->asm_ref = G_OBJECT(layer);
- stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info));
-
- reset_assembly_info(stack->asm_info);
-
- layer = build_progress_status_stack(stack);
- gtk_stack_add_named(stack->main, layer, "prog_info");
-
- stack->prog_ref = G_OBJECT(layer);
- stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info));
-
- reset_progress_info(stack->prog_info);
-
- gtk_status_stack_reset_current_location(stack);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_dispose(GtkStatusStack *stack)
-{
- G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_finalize(GtkStatusStack *stack)
-{
- reset_assembly_info(stack->asm_info);
- free(stack->asm_info);
-
- reset_progress_info(stack->prog_info);
- free(stack->prog_info);
-
- G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée une nouvelle instance de barre de statut. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkStatusStack *gtk_status_stack_new(void)
-{
- GtkStatusStack *result; /* Instance à retourner */
-
- result = g_object_new(GTK_TYPE_STATUS_STACK, NULL);
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : info = informations à réinitialiser. *
-* *
-* Description : Supprime l'empreinte mémoire d'informations d'assemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void reset_assembly_info(assembly_info *info)
-{
- info->reset = true;
-
- if (info->segment != NULL)
- {
- free(info->segment);
- info->segment = NULL;
- }
-
- if (info->symbol != NULL)
- {
- free(info->symbol);
- info->symbol = NULL;
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = composant global en cours de construction. *
-* *
-* Description : Construit une barre d'état pour language d'assemblage. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack)
-{
- GtkWidget *result; /* Support à retourner */
- GObject *ref; /* Espace de référencements */
- GtkWidget *hbox; /* Sous-division horizontale */
- GtkWidget *label; /* Etiquette pour impression */
- GtkWidget *zoom; /* Sélection du zoom courant */
-
- result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show(result);
-
- ref = G_OBJECT(result);
-
- g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref);
-
- /* Première partie : navigation */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8);
-
- label = qck_create_label(ref, "segment", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "phys", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "virt", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "offset", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- /* Seconde partie : architecture */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- g_object_set_data(ref, "arch_box", hbox);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8);
-
- label = qck_create_label(ref, "arch", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "size", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- /* Troisième partie : affichage */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8);
-
- zoom = qck_create_entry(ref, "zoom", "100%");
- gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic");
-
- g_signal_connect(zoom, "focus-in-event", G_CALLBACK(track_focus_change_in_text_area), NULL);
- g_signal_connect(zoom, "focus-out-event", G_CALLBACK(track_focus_change_in_text_area), NULL);
- g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack);
-
- gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant graphique qui vient d'évoluer. *
-* allocation = espace réservé pour le composant visé. *
-* ref = espace de référencement global. *
-* *
-* Description : Réagit à un redimensionnement de la barre de désassemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref)
-{
- GtkWidget *hbox; /* Sous-division horizontale */
-
- hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box"));
-
- gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1);
-
- /**
- * On intervient après que le containeur soit passé collecter les tailles
- * de ses enfants lors de son redimensionnement.
- *
- * Donc on force un prise en compte des changements.
- */
- gtk_container_check_resize(GTK_CONTAINER(widget));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : entry = zone de texte visée par la procédure. *
-* icon_pos = position de l'image associée à l'entrée. *
-* event = informations liées à l'événement. *
-* stack = composant graphique de gestion des statuts. *
-* *
-* Description : Réagit à un clic sur l'icône de zoom. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack)
-{
- GtkWidget *popup; /* Popup à faire surgir */
- GdkRectangle rect; /* Zone précise à cibler */
-
- if (event->button != GDK_BUTTON_PRIMARY)
- return;
-
- popup = gtk_popover_new(GTK_WIDGET(entry));
-
- gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
- gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
-
- gtk_widget_show(popup);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* range = emplacement à mettre en valeur. *
-* segment = zone de binaire d'appartenance. *
-* symbol = éventuelle position par rapport à un symbole. *
-* encoding = encodage d'une éventuelle instruction ou NULL. *
-* *
-* Description : Actualise les informations liées une position d'assemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *encoding)
-{
- assembly_info *info; /* Informations à constituer */
- const vmpa2t *addr; /* Localisation de départ */
- phys_t size; /* Taille de l'emplacement */
-
- info = stack->asm_info;
-
- /* Bascule vers une zone courante nouvelle ? */
-
- addr = get_mrange_addr(range);
- size = get_mrange_length(range);
-
- if (cmp_mrange(&info->current, range) == 0
- && info->size == size
- && info->encoding == encoding)
- goto useless;
-
- /* Réinitialisation */
-
- reset_assembly_info(info);
-
- copy_mrange(&info->current, range);
-
- /* Zone d'appartenance */
-
- info->segment = strdup(segment);
-
- /* Adresses de base */
-
- vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
-
- vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
-
- info->encoding = encoding;
- info->size = size;
-
- /* Symbole concerné */
-
- if (symbol != NULL)
- info->symbol = strdup(symbol);
-
- /* Nettoyage et conclusion */
-
- info->reset = false;
-
- gtk_status_stack_show_current_location(stack);
-
- useless:
-
- ;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* *
-* Description : Réinitialise les informations associées une position. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_reset_current_location(GtkStatusStack *stack)
-{
- assembly_info *info; /* Informations à constituer */
-
- info = stack->asm_info;
-
- reset_assembly_info(info);
-
- gtk_status_stack_show_current_location(stack);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = pile de statuts à manipuler. *
-* *
-* Description : S'assure de l'affichage à jour de la partie "assemblage". *
-* *
-* Retour : G_SOURCE_REMOVE pour une exécution unique. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack)
-{
- GObject *ref; /* Espace de référencements */
- assembly_info *info; /* Informations à consulter */
- GtkLabel *label; /* Etiquette à actualiser */
- char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */
- char *content; /* Contenu dynamique */
-
- stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location;
-
- gtk_stack_set_visible_child_name(stack->main, "asm_info");
-
- ref = stack->asm_ref;
- info = stack->asm_info;
-
- /* Première partie : navigation */
-
- if (info->reset)
- {
- label = GTK_LABEL(g_object_get_data(ref, "segment"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "phys"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "virt"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "offset"));
- gtk_label_set_text(label, NULL);
-
- }
- else
- {
- label = GTK_LABEL(g_object_get_data(ref, "segment"));
- gtk_label_set_text(label, info->segment);
-
- snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
-
- label = GTK_LABEL(g_object_get_data(ref, "phys"));
- gtk_label_set_text(label, raw_pos);
-
- snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
-
- label = GTK_LABEL(g_object_get_data(ref, "virt"));
- gtk_label_set_text(label, raw_pos);
-
- label = GTK_LABEL(g_object_get_data(ref, "offset"));
- gtk_label_set_text(label, info->symbol != NULL ? info->symbol : "");
-
- }
-
- /* Seconde partie : architecture */
-
- if (info->reset || info->encoding == NULL || info->size == VMPA_NO_PHYSICAL)
- {
- label = GTK_LABEL(g_object_get_data(ref, "arch"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "size"));
- gtk_label_set_text(label, NULL);
-
- }
- else
- {
- label = GTK_LABEL(g_object_get_data(ref, "arch"));
- gtk_label_set_text(label, info->encoding);
-
- if (info->size > 1)
- asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes"));
- else
- asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte"));
-
- label = GTK_LABEL(g_object_get_data(ref, "size"));
- gtk_label_set_text(label, content);
-
- free(content);
-
- }
-
- return G_SOURCE_REMOVE;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* STATUT DES SUIVIS D'ACTIVITE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : info = informations à réinitialiser. *
-* *
-* Description : Supprime l'empreinte mémoire d'informations d'activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void reset_progress_info(progress_info *info)
-{
- size_t i; /* Boucle de parcours */
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = 0;
-
- for (i = 0; i < info->count; i++)
- {
- if (info->statuses[i].message != NULL)
- free(info->statuses[i].message);
- }
-
- if (info->statuses != NULL)
- {
- free(info->statuses);
- info->statuses = NULL;
- }
-
- info->count = 0;
-
- g_mutex_init(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = composant global en cours de construction. *
-* *
-* Description : Construit une barre d'état pour un suivi d'activité. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkWidget *build_progress_status_stack(GtkStatusStack *stack)
-{
- GtkWidget *result; /* Support à retourner */
- GObject *ref; /* Espace de référencements */
- GtkWidget *progress; /* Barre de progression */
- GtkWidget *label; /* Désignation de l'activité */
-
- result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show(result);
-
- ref = G_OBJECT(result);
-
- progress = gtk_progress_bar_new();
- g_object_set_data(ref, "progress", progress);
- gtk_widget_set_size_request(progress, PROGRESS_SIZE, -1);
- gtk_widget_set_valign(progress, GTK_ALIGN_CENTER);
- gtk_widget_show(progress);
- gtk_box_pack_start(GTK_BOX(result), progress, FALSE, TRUE, 8);
-
- label = qck_create_label(ref, "message", NULL);
- gtk_box_pack_start(GTK_BOX(result), label, TRUE, TRUE, 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* msg = nouveau message de statut à copier. *
-* max = taille de la plage à parcourir. *
-* *
-* Description : Démarre le suivi d'une nouvelle activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max)
-{
- activity_id_t result; /* Numéro unique à renvoyer */
- progress_info *info; /* Informations à consulter */
- size_t new; /* Indice de l'activité créée */
-
- if (stack == NULL) return NO_ACTIVITY_ID;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- result = ++info->generator;
-
- new = info->count++;
-
- info->statuses = (progress_status *)realloc(info->statuses,
- info->count * sizeof(progress_status));
-
- info->statuses[new].id = result;
-
- /* Intitulé */
-
- if (msg == NULL)
- info->statuses[new].message = NULL;
- else
- info->statuses[new].message = strdup(msg);
-
- /* Valeur */
-
- info->statuses[new].current = 0;
- info->statuses[new].max = max;
- info->statuses[new].last_updated = 0;
-
- /* Actualisation */
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- g_mutex_unlock(&info->access);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* extra = nouvelle échéance supplémentaire des traitements. *
-* *
-* Description : Etend la portée des travaux d'une nouvelle activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- info->statuses[i].max += extra;
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* msg = nouveau message de statut à copier. *
-* *
-* Description : Actualise les informations concernant une activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- bool msg_changed; /* Changement d'intitulé */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- /* Intitulé */
-
- if (info->statuses[i].message != NULL)
- {
- if (msg == NULL)
- msg_changed = true;
- else
- msg_changed = (strcmp(info->statuses[i].message, msg) != 0);
-
- free(info->statuses[i].message);
-
- }
- else
- msg_changed = (msg != NULL);
-
- if (msg == NULL)
- info->statuses[i].message = NULL;
- else
- info->statuses[i].message = strdup(msg);
-
- /* On n'actualise que le sommet de la pile */
-
- if ((i + 1) == info->count && msg_changed)
- {
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- }
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* inc = nouvelle valeur pour une progression donnée. *
-* *
-* Description : Actualise la progression d'une activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- progress_status *status; /* Raccourci de confort */
- double new; /* Nouvelle progression */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- status = &info->statuses[i];
-
- /* Valeur */
-
- status->current += inc;
-
- new = (status->current * 1.0) / status->max;
-
- /* On n'actualise que le sommet de la pile */
-
- if ((i + 1) == info->count && (new - status->last_updated) > (1.0 / PROGRESS_SIZE))
- {
- status->last_updated = new;
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- }
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* *
-* Description : Met fin au suivi d'une activité donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- if (info->statuses[i].message != NULL)
- free(info->statuses[i].message);
-
- if (info->count == 1)
- {
- free(info->statuses);
- info->statuses = NULL;
- }
- else
- {
- memmove(&info->statuses[i], &info->statuses[i + 1],
- (info->count - i - 1) * sizeof(progress_status));
-
- info->statuses = (progress_status *)realloc(info->statuses,
- (info->count - 1) * sizeof(progress_status));
-
- }
-
- info->count--;
-
- if (info->count == 0)
- {
- info->tag = 0;
- g_idle_add(stack->def_source, stack);
- }
- else
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = pile de statuts à manipuler. *
-* *
-* Description : S'assure de l'affichage à jour de la partie "activité". *
-* *
-* Retour : G_SOURCE_REMOVE pour une exécution unique. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack)
-{
- GObject *ref; /* Espace de référencements */
- progress_info *info; /* Informations à consulter */
- progress_status *last; /* Dernier statut à traiter */
- GtkProgressBar *progress; /* Barre de progression */
- GtkLabel *label; /* Désignation de l'activité */
-
- if (!g_source_is_destroyed(g_main_current_source()))
- {
- gtk_stack_set_visible_child_name(stack->main, "prog_info");
-
- ref = stack->prog_ref;
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- info->tag = 0;
-
- if (info->count > 0)
- {
- last = &info->statuses[info->count - 1];
-
- progress = GTK_PROGRESS_BAR(g_object_get_data(ref, "progress"));
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (last->current * 1.0) / last->max);
-
- label = GTK_LABEL(g_object_get_data(ref, "message"));
- gtk_label_set_text(label, last->message);
-
- }
-
- g_mutex_unlock(&info->access);
-
- }
-
- return G_SOURCE_REMOVE;
-
-}
diff --git a/src/gtkext/helpers.h b/src/gtkext/helpers.h
new file mode 100644
index 0000000..3f8b3cd
--- /dev/null
+++ b/src/gtkext/helpers.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers.h - prototypes pour la simplification des interactions de base avec GTK
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_HELPERS_H
+#define _GTKEXT_HELPERS_H
+
+
+#include <assert.h>
+#include <glib-object.h>
+
+
+
+/**
+ * Facilités de transmission de paramètres pour les fonctions de type
+ * gtk_widget_class_bind_template_callback_full() et gtk_builder_cscope_add_callback_symbol().
+ */
+
+#define BUILDER_CB(cb) \
+ #cb, G_CALLBACK(cb)
+
+
+
+#endif /* _GTKEXT_HELPERS_H */
diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c
index 7363079..95b592e 100644
--- a/src/gtkext/hexview.c
+++ b/src/gtkext/hexview.c
@@ -37,17 +37,33 @@
/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
-/* Procède à l'initialisation de l'afficheur générique. */
+/* Liste des propriétés */
+
+typedef enum _HexViewProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_SHOW_OFFSETS, /* Affichage des positions */
+ PROP_CONTENT, /* Contenu binaire affiché */
+
+ N_PROPERTIES
+
+} HexViewProperty;
+
+static GParamSpec *_hex_view_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des afficheurs de tampons bruts. */
static void gtk_hex_view_class_init(GtkHexViewClass *);
-/* Procède à l'initialisation de l'afficheur générique. */
+/* Initialise une instance d'afficheur de tampons bruts. */
static void gtk_hex_view_init(GtkHexView *);
/* Supprime toutes les références externes. */
-static void gtk_hex_view_dispose(GtkHexView *);
+static void gtk_hex_view_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void gtk_hex_view_finalize(GtkHexView *);
+static void gtk_hex_view_finalize(GObject *);
/* Procède à l'actualisation de l'affichage d'un sous-composant. */
static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *, GtkSnapshot *, GtkWidget *);
@@ -57,14 +73,14 @@ static void gtk_hex_view_populate_cache(GtkHexView *);
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent);
-
-
-
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_hex_view_set_property(GObject *, guint, const GValue *, GParamSpec *);
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_hex_view_get_property(GObject *, guint, GValue *, GParamSpec *);
/* Prend acte de la taille allouée au composant d'affichage. */
static void gtk_hex_view_size_allocate(GtkWidget *, int, int, int);
@@ -90,7 +106,7 @@ G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_BUFFER_VIEW);
* *
* Paramètres : class = classe GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur générique. *
+* Description : Initialise la classe des afficheurs de tampons bruts. *
* *
* Retour : - *
* *
@@ -105,12 +121,26 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_hex_view_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_hex_view_finalize;
+ object->dispose = gtk_hex_view_dispose;
+ object->finalize = gtk_hex_view_finalize;
+ object->set_property = gtk_hex_view_set_property;
+ object->get_property = gtk_hex_view_get_property;
+
+ _hex_view_properties[PROP_SHOW_OFFSETS] =
+ g_param_spec_boolean("show-offsets", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ _hex_view_properties[PROP_CONTENT] =
+ g_param_spec_object("content", NULL, NULL,
+ G_TYPE_BIN_CONTENT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _hex_view_properties);
widget = GTK_WIDGET_CLASS(class);
- gtk_widget_class_set_css_name(widget, "GtkHexView");
+ gtk_widget_class_set_css_name(widget, "hexview");
g_type_ensure(GTK_TYPE_COMPOSING_AREA);
@@ -131,7 +161,7 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
* *
* Paramètres : view = composant GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur générique. *
+* Description : Initialise une instance d'afficheur de tampons bruts. *
* *
* Retour : - *
* *
@@ -167,12 +197,14 @@ static void gtk_hex_view_init(GtkHexView *view)
view->generator = NULL;
+ gtk_hex_view_create(view, NULL);
+
}
/******************************************************************************
* *
-* Paramètres : view = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -182,20 +214,24 @@ static void gtk_hex_view_init(GtkHexView *view)
* *
******************************************************************************/
-static void gtk_hex_view_dispose(GtkHexView *view)
+static void gtk_hex_view_dispose(GObject *object)
{
- gtk_widget_dispose_template(GTK_WIDGET(view), GTK_TYPE_HEX_VIEW);
+ GtkHexView *view; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_HEX_VIEW);
+
+ view = GTK_HEX_VIEW(object);
g_clear_object(&view->generator);
- G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(G_OBJECT(view));
+ G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : view = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -205,9 +241,9 @@ static void gtk_hex_view_dispose(GtkHexView *view)
* *
******************************************************************************/
-static void gtk_hex_view_finalize(GtkHexView *view)
+static void gtk_hex_view_finalize(GObject *object)
{
- G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(G_OBJECT(view));
+ G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(object);
}
@@ -263,13 +299,43 @@ bool gtk_hex_view_create(GtkHexView *view, GBinContent *content)
parent = GTK_BUFFER_VIEW(view);
- cache = g_buffer_cache_new(1, 2);
+ cache = g_buffer_cache_new(1 /* opt_count */, 2 /* reg_count */);
parent->view = g_buffer_view_new(cache, parent->style);
unref_object(cache);
- view->generator = g_hex_generator_new(content);
+
+
+ gtk_hex_view_set_content(view, content);
+
+
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = composant d'affichage à consulter. *
+* *
+* Description : Fournit le contenu associé au composant d'affichage. *
+* *
+* Retour : Contenu dans lequel puise le générateur pour les lignes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *gtk_hex_view_get_content(const GtkHexView *view)
+{
+ GBinContent *result; /* Référence à retourner */
+
+ if (view->generator != NULL)
+ result = g_hex_generator_get_content(view->generator);
+ else
+ result = NULL;
return result;
@@ -278,6 +344,61 @@ bool gtk_hex_view_create(GtkHexView *view, GBinContent *content)
/******************************************************************************
* *
+* Paramètres : view = composant d'affichage à modifier. *
+* content = nouveau contenu pour source de génération. *
+* *
+* Description : Définit le contenu associé au composant d'affichage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_hex_view_set_content(GtkHexView *view, GBinContent *content)
+{
+ GBinContent *old; /* Ancienne valeur */
+ GBufferCache *cache; /* Tampon à représenter */
+
+ old = gtk_hex_view_get_content(view);
+
+ assert((old == NULL && view->generator == NULL) || (old != NULL && view->generator != NULL));
+
+ if (old != content)
+ {
+ if (view->generator != NULL)
+ {
+ cache = g_buffer_view_get_cache(GTK_BUFFER_VIEW(view)->view);
+
+ g_buffer_cache_wlock(cache);
+
+ g_buffer_cache_truncate(cache, 0);
+
+ g_buffer_cache_wunlock(cache);
+
+ unref_object(cache);
+
+ g_clear_object(&view->generator);
+
+ }
+
+ if (content != NULL)
+ view->generator = g_hex_generator_new(content);
+
+ g_object_notify_by_pspec(G_OBJECT(view), _hex_view_properties[PROP_CONTENT]);
+
+ assert(content != NULL);
+ gtk_widget_queue_resize(GTK_WIDGET(view));
+
+ }
+
+ g_clear_object(&old);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : widget = composant GTK à redessiner. *
* snapshot = gestionnaire de noeuds de rendu à solliciter. *
* parent = composant GTK parent et cadre de l'appel. *
@@ -380,67 +501,108 @@ static void gtk_hex_view_populate_cache(GtkHexView *view)
/* Mise à jour de l'affichage ? */
+ /*
if (needed != count)
gtk_widget_queue_resize(GTK_WIDGET(view));
+ */
}
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent)
+static void gtk_hex_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- GdkRGBA red, green, yellow, blue;
- float w, h;
-
- gdk_rgba_parse (&red, "red");
- gdk_rgba_parse (&green, "green");
- gdk_rgba_parse (&yellow, "yellow");
- gdk_rgba_parse (&blue, "blue");
+ GtkHexView *view; /* Version spécialisée */
+ GObject *content; /* Contenu sous forme simple */
- w = gtk_widget_get_width (widget) / 2.0;
- h = gtk_widget_get_height (widget) / 2.0;
+ view = GTK_HEX_VIEW(object);
- h /= 2.0;
+ switch (prop_id)
+ {
+ case PROP_SHOW_OFFSETS:
+ g_display_options_set(GTK_CONTENT_VIEW(view)->options, HCO_OFFSET, g_value_get_boolean(value));
+ gtk_widget_set_visible(view->offsets, g_value_get_boolean(value));
+ break;
- gtk_snapshot_append_color (snapshot, &red,
- &GRAPHENE_RECT_INIT(0, 0, w, h));
- gtk_snapshot_append_color (snapshot, &green,
- &GRAPHENE_RECT_INIT(w, 0, w, h));
- gtk_snapshot_append_color (snapshot, &yellow,
- &GRAPHENE_RECT_INIT(0, h, w, h));
- gtk_snapshot_append_color (snapshot, &blue,
- &GRAPHENE_RECT_INIT(w, h, w, h));
+ case PROP_CONTENT:
+ content = g_value_get_object(value);
+ gtk_hex_view_set_content(view, G_BIN_CONTENT(content));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
}
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static void gtk_hex_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkHexView *view; /* Version spécialisée */
+ view = GTK_HEX_VIEW(object);
+ switch (prop_id)
+ {
+ case PROP_SHOW_OFFSETS:
+ g_value_set_boolean(value, gtk_widget_get_visible(view->offsets));
+ break;
+ case PROP_CONTENT:
+ g_value_take_object(value, gtk_hex_view_get_content(view));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
-
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
+}
/******************************************************************************
* *
-* Paramètres : widget = composant GTK à examiner. *
-* width = largeur affectée au composant graphique. *
-* height = hauteur affectée au composant graphique. *
+* Paramètres : widget = composant GTK à examiner. *
+* width = largeur affectée au composant graphique. *
+* height = hauteur affectée au composant graphique. *
* baseline = ligne de base affectée au composant graphique. *
* *
* Description : Prend acte de la taille allouée au composant d'affichage. *
@@ -467,7 +629,13 @@ static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height,
final_widths = alloca(_CHILDREN_COUNT * sizeof(int));
for (i = 0; i < _CHILDREN_COUNT; i++)
- gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL);
+ {
+ if (!gtk_widget_get_visible(view->children[i]))
+ min_widths[i] = 0;
+ else
+ gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL);
+
+ }
/* Passe 1 : tentative sans défilement vertical */
@@ -491,7 +659,10 @@ static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height,
for (i = 0; i < _CHILDREN_COUNT; i++)
{
- final_widths[i] += min_widths[i];
+ if (!gtk_widget_get_visible(view->children[i]))
+ final_widths[i] = 0;
+ else
+ final_widths[i] += min_widths[i];
g_width_tracker_set_column_min_width(tracker, i, final_widths[i]);
@@ -531,17 +702,6 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget)
}
-
-
-
-
-
-
-
-
-
-
-
/******************************************************************************
* *
* Paramètres : widget = composant GTK à examiner. *
@@ -580,8 +740,12 @@ static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation,
for (i = 0; i < _CHILDREN_COUNT; i++)
{
+ if (!gtk_widget_get_visible(view->children[i]))
+ continue;
+
gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
requested += min;
+
}
for_size -= requested;
@@ -593,11 +757,14 @@ static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation,
GTK_BUFFER_VIEW(view)->style,
for_size);
- if (minimum != NULL) *minimum = 0;
+ if (minimum != NULL) *minimum = requested;
if (natural != NULL) *natural = requested;
for (i = 0; i < _CHILDREN_COUNT; i++)
{
+ if (!gtk_widget_get_visible(view->children[i]))
+ continue;
+
gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL);
if (minimum != NULL && min > *minimum)
diff --git a/src/gtkext/hexview.h b/src/gtkext/hexview.h
index 2199786..0d2cd5a 100644
--- a/src/gtkext/hexview.h
+++ b/src/gtkext/hexview.h
@@ -41,6 +41,12 @@ DECLARE_GTYPE(GtkHexView, gtk_hex_view, GTK, HEX_VIEW);
/* Crée un composant d'affichage d'octets bruts et imprimables. */
GtkHexView *gtk_hex_view_new(GBinContent *);
+/* Fournit le contenu associé au composant d'affichage. */
+GBinContent *gtk_hex_view_get_content(const GtkHexView *);
+
+/* Définit le contenu associé au composant d'affichage. */
+void gtk_hex_view_set_content(GtkHexView *, GBinContent *);
+
#endif /* _GTKEXT_HEXVIEW_H */
diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui
index ae4586c..9b42936 100644
--- a/src/gtkext/hexview.ui
+++ b/src/gtkext/hexview.ui
@@ -1,27 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <template class="GtkHexView" parent="GtkBufferView">
- <property name="css-name">GtkHexView</property>
- <child>
- <object class="GtkComposingArea" id="offsets">
- <style>
- <class name="gutter"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkComposingArea" id="hex">
- <property name="hexpand">true</property>
- <style>
- <class name="custom-view"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkComposingArea" id="ascii">
- <style>
- <class name="custom-view"/>
- </style>
- </object>
- </child>
- </template>
+
+ <template class="GtkHexView" parent="GtkBufferView">
+ <child>
+ <object class="GtkComposingArea" id="offsets">
+ <style>
+ <class name="gutter"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComposingArea" id="hex">
+ <property name="hexpand">true</property>
+ <style>
+ <class name="custom-view"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComposingArea" id="ascii">
+ <style>
+ <class name="custom-view"/>
+ </style>
+ </object>
+ </child>
+ </template>
+
</interface>
diff --git a/src/gtkext/launcher-int.h b/src/gtkext/launcher-int.h
new file mode 100644
index 0000000..07152f0
--- /dev/null
+++ b/src/gtkext/launcher-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak-int.h - définitions internes pour un lanceur de panneau majeur
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_LAUNCHER_INT_H
+#define _GTKEXT_LAUNCHER_INT_H
+
+
+#include "launcher.h"
+
+
+
+/* Elément de lancement d'un panneau majeur pour l'interface (instance) */
+struct _GtkPanelLauncher
+{
+ GtkListBoxRow parent; /* A laisser en premier */
+
+ GtkImage *icon; /* Eventuelle image */
+ GtkLabel *title; /* Etiquette associée */
+ GtkLabel *desc; /* Description du panneau */
+
+};
+
+/* Elément de lancement d'un panneau majeur pour l'interface (classe) */
+struct _GtkPanelLauncherClass
+{
+ GtkListBoxRowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouveau lanceur de panneau majeur. */
+bool gtk_panel_launcher_create(GtkPanelLauncher *, const char *, const char *, const char *);
+
+
+
+#endif /* _GTKEXT_LAUNCHER_INT_H */
diff --git a/src/gtkext/launcher.c b/src/gtkext/launcher.c
new file mode 100644
index 0000000..5bb850b
--- /dev/null
+++ b/src/gtkext/launcher.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * launcher.c - lanceur de panneau majeur
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "launcher.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "helpers.h"
+#include "launcher-int.h"
+#include "../common/extstr.h"
+
+
+
+/* Initialise la classe des sections d'éléments paramétrables. */
+static void gtk_panel_launcher_class_init(GtkPanelLauncherClass *);
+
+/* Initialise une instance de lanceur de panneau majeur. */
+static void gtk_panel_launcher_init(GtkPanelLauncher *);
+
+/* Supprime toutes les références externes. */
+static void gtk_panel_launcher_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_panel_launcher_finalize(GObject *);
+
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkPanelLauncher, gtk_panel_launcher, GTK_TYPE_LIST_BOX_ROW);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des sections d'éléments paramétrables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_class_init(GtkPanelLauncherClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_panel_launcher_dispose;
+ object->finalize = gtk_panel_launcher_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/launcher.ui");
+
+ gtk_widget_class_bind_template_child(widget, GtkPanelLauncher, icon);
+ gtk_widget_class_bind_template_child(widget, GtkPanelLauncher, title);
+ gtk_widget_class_bind_template_child(widget, GtkPanelLauncher, desc);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : launcher = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de lanceur de panneau majeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_init(GtkPanelLauncher *launcher)
+{
+ gtk_widget_init_template(GTK_WIDGET(launcher));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_PANEL_LAUNCHER);
+
+ G_OBJECT_CLASS(gtk_panel_launcher_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_panel_launcher_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : icon = désignation de l'image de représentation. *
+* title = titre principal à afficher. *
+* desc = description du panneau ciblé. *
+* *
+* Description : Crée un nouveau lanceur de panneau majeur. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkPanelLauncher *gtk_panel_launcher_new(const char *icon, const char *title, const char *desc)
+{
+ GtkPanelLauncher *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_PANEL_LAUNCHER, NULL);
+
+ if (!gtk_panel_launcher_create(result, icon, title, desc))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : launcher = lanceur à initialiser pleinement. *
+* icon = désignation de l'image de représentation. *
+* title = titre principal à afficher. *
+* desc = description du panneau ciblé. *
+* *
+* Description : Met en place un nouveau lanceur de panneau majeur. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_launcher_create(GtkPanelLauncher *launcher, const char *icon, const char *title, const char *desc)
+{
+ bool result; /* Bilan à retourner */
+ char *bold; /* Titre sublimé */
+
+ result = true;
+
+ gtk_image_set_from_icon_name(launcher->icon, icon);
+
+ bold = strdup(title);
+ bold = strprep(bold, "<b>");
+ bold = stradd(bold, "</b>");
+
+ gtk_label_set_label(launcher->title, bold);
+
+ free(bold);
+
+ gtk_label_set_label(launcher->desc, desc);
+
+ return result;
+
+}
diff --git a/src/gtkext/launcher.h b/src/gtkext/launcher.h
new file mode 100644
index 0000000..3857216
--- /dev/null
+++ b/src/gtkext/launcher.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * launcher.h - prototypes pour pour un lanceur de panneau majeur
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_LAUNCHER_H
+#define _GTKEXT_LAUNCHER_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_PANEL_LAUNCHER (gtk_panel_launcher_get_type())
+
+DECLARE_GTYPE(GtkPanelLauncher, gtk_panel_launcher, GTK, PANEL_LAUNCHER);
+
+
+/* Crée un nouveau lanceur de panneau majeur. */
+GtkPanelLauncher *gtk_panel_launcher_new(const char *, const char *, const char *);
+
+
+
+#endif /* _GTKEXT_LAUNCHER_H */
diff --git a/src/gtkext/launcher.ui b/src/gtkext/launcher.ui
new file mode 100644
index 0000000..f6f4fec
--- /dev/null
+++ b/src/gtkext/launcher.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkPanelLauncher" parent="GtkListBoxRow">
+
+ <property name="child">
+
+ <object class="GtkGrid">
+ <property name="margin-bottom">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">12</property>
+ <property name="column-spacing">12</property>
+
+ <child>
+ <object class="GtkImage" id="icon">
+ <property name="icon-name"></property>
+ <property name="pixel-size">48</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="label"></property>
+ <property name="use-markup">TRUE</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="desc">
+ <property name="label"></property>
+ <property name="hexpand">true</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="margin-start">12</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+
+ </property>
+
+ </template>
+</interface>
diff --git a/src/gui/panel-int.h b/src/gtkext/panel-int.h
index d54dc16..5398e51 100644
--- a/src/gui/panel-int.h
+++ b/src/gtkext/panel-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* panel-int.h - prototypes pour les définitions internes liées aux panneaux d'affichage
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -22,13 +22,52 @@
*/
-#ifndef _GUI_PANELS_PANEL_INT_H
-#define _GUI_PANELS_PANEL_INT_H
+#ifndef _GTKEXT_PANEL_INT_H
+#define _GTKEXT_PANEL_INT_H
#include "panel.h"
+
+/* Indique l'emplacement par défaut pour un affichage. */
+typedef char * (* get_tiled_panel_path) (const GtkTiledPanel *);
+
+/* Fournit les composants adaptés pour la barre de titre. */
+typedef GListStore * (* get_tiled_panel_widgets_cb) (const GtkTiledPanel *, bool);
+
+/* Note un ajout ou un retrait de panneau principal. */
+typedef void (* notify_tiled_panel_state_cb) (GtkTiledPanel *, GtkTiledPanel *, bool);
+
+
+/* Elément réactif pour panneaux de l'éditeur (instance) */
+struct _GtkTiledPanel
+{
+ GtkBox parent; /* A laisser en premier */
+
+};
+
+/* Elément réactif pour panneaux de l'éditeur (classe) */
+struct _GtkTiledPanelClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+ get_tiled_panel_path get_default_path; /* Localisation de l'affichage */
+ get_tiled_panel_widgets_cb get_widgets; /* Récupération de composants */
+
+ notify_tiled_panel_state_cb notify; /* Note d'un ajout ou retrait */
+
+};
+
+
+
+
+
+
+
+
+#if 0
+
#include <gtk/gtk.h>
@@ -134,5 +173,8 @@ void g_panel_item_switch_to_updating_mask(GPanelItem *);
void g_panel_item_switch_to_updated_content(GPanelItem *);
+#endif
+
+
-#endif /* _GUI_PANELS_PANEL_INT_H */
+#endif /* _GTKEXT_PANEL_INT_H */
diff --git a/src/gui/panel.c b/src/gtkext/panel.c
index 5b21620..f63cfa1 100644
--- a/src/gui/panel.c
+++ b/src/gtkext/panel.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* panel.c - gestion des éléments réactifs spécifiques aux panneaux
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,6 +25,206 @@
#include "panel.h"
+#include "panel-int.h"
+
+
+
+
+
+/* Initialise la classe des panneaux graphiques de l'éditeur. */
+static void gtk_tiled_panel_class_init(GtkTiledPanelClass *);
+
+/* Initialise une instance de panneau graphique pour l'éditeur. */
+static void gtk_tiled_panel_init(GtkTiledPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_tiled_panel_dispose(GtkTiledPanel *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_tiled_panel_finalize(GtkTiledPanel *);
+
+
+
+
+
+
+
+
+/* Détermine le type du conteneur d'affichage en tuiles nommées. */
+G_DEFINE_TYPE(GtkTiledPanel, gtk_tiled_panel, GTK_TYPE_BOX)
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des panneaux graphiques de l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_class_init(GtkTiledPanelClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tiled_panel_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_tiled_panel_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance GTK à initialiser. *
+* *
+* Description : Initialise une instance de panneau graphique pour l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_init(GtkTiledPanel *panel)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_dispose(GtkTiledPanel *panel)
+{
+ G_OBJECT_CLASS(gtk_tiled_panel_parent_class)->dispose(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_finalize(GtkTiledPanel *panel)
+{
+ G_OBJECT_CLASS(gtk_tiled_panel_parent_class)->finalize(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
+* *
+* Description : Indique l'emplacement attendu pour un affichage. *
+* *
+* Retour : Chemin représenté ou NULL pour l'emplacement "M" par défaut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *gtk_tiled_panel_get_path(const GtkTiledPanel *panel)
+{
+ char *result; /* Chemin à retourner */
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->get_default_path != NULL)
+ result = class->get_default_path(panel);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
+* left = indication quant au côté ciblé. *
+* *
+* Description : Fournit les composants adaptés pour la barre de titre. *
+* *
+* Retour : Liste de Composants GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *panel, bool left)
+{
+ GListStore *result; /* Composant(s) à retourner */
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->get_widgets != NULL)
+ result = class->get_widgets(panel, left);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiled_panel_notify_new_main_panel_state(GtkTiledPanel *panel, GtkTiledPanel *main, bool activated)
+{
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->notify != NULL)
+ class->notify(panel, main, activated);
+
+}
+
+
+
+
+
+
+#if 0
+
#include <assert.h>
#include <stdio.h>
#include <string.h>
@@ -859,7 +1059,7 @@ void g_panel_item_set_dock_at_startup(GPanelItem *item, bool status)
bool g_panel_item_is_docked(const GPanelItem *item)
{
- bool result; /* Status à retourner */
+ bool result; /* Statut à retourner */
result = item->docked;
@@ -1117,3 +1317,5 @@ void g_panel_item_switch_to_updated_content(GPanelItem *item)
g_atomic_int_dec_and_test(&item->switched);
}
+
+#endif
diff --git a/src/gui/panel.h b/src/gtkext/panel.h
index de8d2bf..9b00657 100644
--- a/src/gui/panel.h
+++ b/src/gtkext/panel.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* panel.h - prototypes pour la gestion des éléments réactifs spécifiques aux panneaux
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -22,10 +22,38 @@
*/
-#ifndef _GUI_PANELS_PANEL_H
-#define _GUI_PANELS_PANEL_H
+#ifndef _GTKEXT_PANEL_H
+#define _GTKEXT_PANEL_H
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_TILED_PANEL (gtk_tiled_panel_get_type())
+
+DECLARE_GTYPE(GtkTiledPanel, gtk_tiled_panel, GTK, TILED_PANEL);
+
+
+/* Indique l'emplacement attendu pour un affichage. */
+char *gtk_tiled_panel_get_path(const GtkTiledPanel *);
+
+/* Fournit les composants adaptés pour la barre de titre. */
+GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *, bool);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_tiled_panel_notify_new_main_panel_state(GtkTiledPanel *, GtkTiledPanel *, bool);
+
+
+
+
+
+
+#if 0
+
#include <stdbool.h>
#include <gtk/gtk.h>
@@ -108,5 +136,7 @@ bool g_panel_item_is_docked(const GPanelItem *);
void g_panel_item_undock(GPanelItem *);
+#endif
+
-#endif /* _GUI_PANELS_PANEL_H */
+#endif /* _GTKEXT_PANEL_H */
diff --git a/src/gtkext/statusstack-int.h b/src/gtkext/statusstack-int.h
new file mode 100644
index 0000000..721b982
--- /dev/null
+++ b/src/gtkext/statusstack-int.h
@@ -0,0 +1,106 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * statusstack-int.h - définitions internes pour l'empilement d'informations de statut
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_STATUSSTACK_INT_H
+#define _GTKEXT_STATUSSTACK_INT_H
+
+
+#include "statusstack.h"
+#include "../glibext/secstorage.h"
+
+
+
+/* Navigation au sein d'assemblage */
+typedef struct _navigation_info_t navigation_info_t;
+
+/* Mémorisation des progressions au sein d'activités */
+typedef struct _activity_info_t activity_info_t;
+
+
+#define NETWORK_UPDATE_COUNT 10
+#define NETWORK_UPDATE_INTERVAL (1000 / NETWORK_UPDATE_COUNT)
+
+
+/* Gestion de barre de statut adaptable (instance) */
+struct _GtkStatusStack
+{
+ GtkBox parent; /* A laisser en premier */
+
+ GtkStack *main; /* Pile d'informations associée*/
+
+ GSourceFunc def_source; /* Appel en fin d'activité */
+
+ /* Message simple par défaut */
+
+ GtkLabel *def_label; /* Afficheur de message */
+
+ char *msg; /* Contenu associé */
+
+ /* Navigation */
+
+ GtkLabel *nav_segment; /* Désignation du segment */
+ GtkLabel *nav_phys; /* Adresse physique */
+ GtkLabel *nav_virt; /* Adresse virtuelle */
+ GtkLabel *nav_offset; /* Position dans le binaire */
+ GtkLabel *nav_format; /* Architecture du binaire */
+ GtkLabel *nav_details; /* Détails sur l'architecture */
+ GtkEntry *zoom; /* Degré de zoom courant */
+
+ navigation_info_t *nav_info; /* Informations brutes liées */
+
+ /* Activité */
+
+ GtkLabel *activity_message; /* Nature de l'activité */
+ GtkProgressBar *activity_progress; /* Barre de progression */
+
+ activity_info_t *activity_info; /* Informations brutes liées */
+
+ /* Tronc commun */
+
+ GSecretStorage *storage; /* Stockage des secrets */
+ GtkToggleButton *lock_update; /* Activation des accès */
+
+ GtkLabel *net_recv_speed; /* Débit en réception */
+ GtkLabel *net_send_speed; /* Débit en émission */
+
+ size_t last_bytes_received[NETWORK_UPDATE_COUNT]; /* Octets reçus */
+ size_t last_bytes_sent[NETWORK_UPDATE_COUNT]; /* Octets émis */
+ gint64 last_timestamps[NETWORK_UPDATE_COUNT]; /* Dates des mesures */
+ size_t next_index; /* Indice d'écriture */
+
+ guint network_update_tag; /* Identifiant de mise à jour */
+
+ GtkToggleButton *bottom_toggler; /* Bascule de panneaux inf. */
+
+};
+
+/* Gestion de barre de statut adaptable (classe) */
+struct _GtkStatusStackClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GTKEXT_STATUSSTACK_INT_H */
diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c
new file mode 100644
index 0000000..92c296a
--- /dev/null
+++ b/src/gtkext/statusstack.c
@@ -0,0 +1,1383 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * statusstack.c - empilement d'informations de statut
+ *
+ * Copyright (C) 2015-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "statusstack.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "helpers.h"
+#include "statusstack-int.h"
+#include "../core/global.h"
+
+
+
+/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _StatusStackProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_SHOW_BOTTOM, /* Affichage de la zone inf. */
+
+ N_PROPERTIES
+
+} StatusStackProperty;
+
+static GParamSpec *_status_stack_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Source d'affichage par défaut */
+#define gtk_status_stack_default_source gtk_status_stack_show_simple_message
+
+
+/* Initialise la classe des barres de statut améliorées. */
+static void gtk_status_stack_class_init(GtkStatusStackClass *);
+
+/* Initialise une instance de barre de statut améliorée. */
+static void gtk_status_stack_init(GtkStatusStack *);
+
+/* Supprime toutes les références externes. */
+static void gtk_status_stack_dispose(GtkStatusStack *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_status_stack_finalize(GtkStatusStack *);
+
+/* Note le changement de verrouillage du stockage sécurisé. */
+static void gtk_status_stack_on_secret_storage_lock_update(GSecretStorage *, GtkStatusStack *);
+
+/* Met à jour dans la barre les débits réseau observés. */
+static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_status_stack_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_status_stack_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ----------------------- MISE EN AVANT DES MESSAGES SIMPLES ----------------------- */
+
+
+/* S'assure de l'affichage à jour de la partie "default". */
+static gboolean gtk_status_stack_show_simple_message(gpointer);
+
+
+
+/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
+
+
+/* Navigation au sein d'assemblage */
+struct _navigation_info_t
+{
+ char *segment; /* Segment d'appartenance */
+
+ mrange_t current; /* Emplacement correspondant */
+
+ VMPA_BUFFER(phys); /* Localisation physique */
+ VMPA_BUFFER(virt); /* Localisation virtuelle */
+
+ char *symbol; /* Eventuel symbole concerné */
+
+ char *format; /* Architecture et format */
+ char *details; /* Encodage de l'instruction */
+
+};
+
+
+/* Met en place le suivi d'informations de navigation. */
+static void init_navigation_info(navigation_info_t *);
+
+/* Supprime l'empreinte mémoire d'informations de navigation. */
+static void fini_navigation_info(navigation_info_t *);
+
+/* S'assure de l'affichage à jour de la partie "navigation". */
+static gboolean gtk_status_stack_show_current_location(gpointer);
+
+/* Réagit à un clic sur l'icône de zoom. */
+static void gtk_status_stack_on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GtkStatusStack *);
+
+
+
+/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */
+
+
+/* Informations de progression */
+typedef struct _activity_status_t
+{
+ activity_id_t id; /* Identifiant unique */
+
+ char *message; /* Indication à faire valoir */
+
+ unsigned long current; /* Position courante */
+ unsigned long max; /* Couverture à parcourir */
+
+ double last_updated; /* Dernière valeur poussée */
+
+} activity_status_t;
+
+
+/* Mémorisation des progressions au sein d'activités */
+struct _activity_info_t
+{
+ GMutex access; /* Accès à la pile */
+
+ activity_id_t generator; /* Générateur de séquence */
+
+ activity_status_t *statuses; /* Statuts de progression */
+ size_t count; /* Nombre de ces statuts */
+
+ guint tag; /* Identifiant de mise à jour */
+
+};
+
+
+/* Met en place le suivi d'informations d'activité. */
+static void init_activity_info(activity_info_t *);
+
+/* Supprime l'empreinte mémoire d'informations d'activité. */
+static void fini_activity_info(activity_info_t *);
+
+/* Recherche les indications de statut d'une activité donnée. */
+static activity_status_t *find_activity_status_by_id(activity_info_t *, activity_id_t);
+
+/* S'assure de l'affichage à jour de la partie "activité". */
+static gboolean gtk_status_stack_show_current_activity(gpointer);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION GENERALE DES STATUTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des barres de statut améliorées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_class_init(GtkStatusStackClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
+ object->set_property = gtk_status_stack_set_property;
+ object->get_property = gtk_status_stack_get_property;
+
+ _status_stack_properties[PROP_SHOW_BOTTOM] =
+ g_param_spec_boolean("show-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _status_stack_properties);
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/statusstack.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press));
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, main);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, def_label);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_segment);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_phys);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_virt);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_offset);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_format);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_details);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, zoom);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, activity_message);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, activity_progress);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, lock_update);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_recv_speed);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_send_speed);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, bottom_toggler);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de barre de statut améliorée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_init(GtkStatusStack *stack)
+{
+ gtk_widget_init_template(GTK_WIDGET(stack));
+
+ stack->def_source = gtk_status_stack_default_source;
+
+ stack->msg = NULL;
+
+ stack->nav_info = calloc(1, sizeof(navigation_info_t));
+ init_navigation_info(stack->nav_info);
+
+ stack->activity_info = calloc(1, sizeof(activity_info_t));
+ init_activity_info(stack->activity_info);
+
+ /* Suivi des évolutions relatives au stockage sécurisé */
+
+ stack->storage = get_secret_storage();
+
+ g_signal_connect(stack->storage, "lock-update",
+ G_CALLBACK(gtk_status_stack_on_secret_storage_lock_update), stack);
+
+ gtk_status_stack_on_secret_storage_lock_update(stack->storage, stack);
+
+ /* Suivi des débits de connexion */
+
+ stack->next_index = 0;
+
+ stack->network_update_tag = g_timeout_add(NETWORK_UPDATE_INTERVAL,
+ G_SOURCE_FUNC(gtk_status_stack_update_network_stats), stack);
+
+ /* Premier affichage... */
+
+ gtk_status_stack_reset_to_default(stack);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_dispose(GtkStatusStack *stack)
+{
+ if (stack->storage != NULL)
+ g_signal_handlers_disconnect_by_func(stack->storage,
+ gtk_status_stack_on_secret_storage_lock_update, stack);
+
+ g_clear_object(&stack->storage);
+
+ g_source_remove(stack->network_update_tag);
+
+ gtk_widget_dispose_template(GTK_WIDGET(stack), GTK_TYPE_STATUS_STACK);
+
+ G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_finalize(GtkStatusStack *stack)
+{
+ if (stack->msg != NULL)
+ free(stack->msg);
+
+ fini_navigation_info(stack->nav_info);
+ free(stack->nav_info);
+
+ fini_activity_info(stack->activity_info);
+ free(stack->activity_info);
+
+ G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une nouvelle instance de barre de statut. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkStatusStack *gtk_status_stack_new(void)
+{
+ GtkStatusStack *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_STATUS_STACK, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* *
+* Description : Réinitialise la barre de statut à son stade par défaut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_reset_to_default(GtkStatusStack *stack)
+{
+ /**
+ * Une amélioration possible serait de passer à g_idle_add_once(),
+ * et de s'affranchir des retours G_SOURCE_REMOVE systématiques,
+ * mais la fonction n'est disponible qu'à partir de la GLib 2.74.
+ */
+
+ g_idle_add(stack->def_source, stack);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gardien des secrets impliqué. *
+* stack = barre de statut à actualiser. *
+* *
+* Description : Note le changement de verrouillage du stockage sécurisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_on_secret_storage_lock_update(GSecretStorage *storage, GtkStatusStack *stack)
+{
+ if (!g_secret_storage_has_key(stack->storage))
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(stack->lock_update), false);
+ gtk_button_set_icon_name(GTK_BUTTON(stack->lock_update), "nolock-symbolic");
+ }
+ else
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(stack->lock_update), true);
+
+ if (g_secret_storage_is_locked(stack->storage))
+ gtk_button_set_icon_name(GTK_BUTTON(stack->lock_update), "locked-symbolic");
+ else
+ gtk_button_set_icon_name(GTK_BUTTON(stack->lock_update), "unlocked-symbolic");
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* *
+* Description : Met à jour dans la barre les débits réseau observés. *
+* *
+* Retour : G_SOURCE_CONTINUE pour poursuivre les mises à jour. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *stack)
+{
+ gboolean result; /* Indication à retourner */
+ gint64 timestamp; /* Position temporelle */
+ size_t received; /* Quantité d'octets reçus */
+ size_t sent; /* Quantité d'octets émis */
+ gint64 diff_time; /* Différentiel de temps */
+ size_t diff_bytes; /* Différentiel de volume */
+ double speed; /* Débit de transfert constaté */
+ size_t i; /* Boucle de parcours */
+ char *value; /* Valeur à afficher */
+
+ const char *units[] = { _("b/s"), _("kb/s"), _("Mb/s"), _("Gb/s"), _("Tb/s") };
+
+ result = G_SOURCE_CONTINUE;
+
+ /* Mémorisation des données */
+
+ timestamp = g_get_monotonic_time();
+
+ get_network_stats(&received, &sent);
+
+ if (stack->next_index < NETWORK_UPDATE_COUNT)
+ {
+ stack->last_bytes_received[stack->next_index] = received;
+ stack->last_bytes_sent[stack->next_index] = sent;
+ stack->last_timestamps[stack->next_index] = timestamp;
+
+ stack->next_index++;
+
+ }
+ else
+ {
+ memcpy(stack->last_bytes_received, stack->last_bytes_received + 1,
+ (NETWORK_UPDATE_COUNT - 1) * sizeof(size_t));
+
+ memcpy(stack->last_bytes_sent, stack->last_bytes_sent + 1,
+ (NETWORK_UPDATE_COUNT - 1) * sizeof(size_t));
+
+ memcpy(stack->last_timestamps, stack->last_timestamps + 1,
+ (NETWORK_UPDATE_COUNT - 1) * sizeof(gint64));
+
+ stack->last_bytes_received[NETWORK_UPDATE_COUNT - 1] = received;
+ stack->last_bytes_sent[NETWORK_UPDATE_COUNT - 1] = sent;
+ stack->last_timestamps[NETWORK_UPDATE_COUNT - 1] = timestamp;
+
+ }
+
+ if (stack->next_index < NETWORK_UPDATE_COUNT)
+ goto done;
+
+ diff_time = stack->last_timestamps[NETWORK_UPDATE_COUNT - 1] - stack->last_timestamps[0];
+
+ /* Débit de réception */
+
+ diff_bytes = stack->last_bytes_received[NETWORK_UPDATE_COUNT - 1] - stack->last_bytes_received[0];
+
+ speed = (diff_bytes * 1000000) / diff_time;
+
+ for (i = 0; i < G_N_ELEMENTS(units); i++)
+ {
+ if (speed < 1024)
+ break;
+
+ speed /= 1024;
+
+ }
+
+ if (i == 0)
+ asprintf(&value, "%d %s", (int)speed, units[i]);
+ else
+ asprintf(&value, "%.1f %s", speed, units[i]);
+
+ gtk_label_set_label(stack->net_recv_speed, value);
+
+ free(value);
+
+ /* Débit de émission */
+
+ diff_bytes = stack->last_bytes_sent[NETWORK_UPDATE_COUNT - 1] - stack->last_bytes_sent[0];
+
+ speed = (diff_bytes * 1000000) / diff_time;
+
+ for (i = 0; i < G_N_ELEMENTS(units); i++)
+ {
+ if (speed < 1024)
+ break;
+
+ speed /= 1024;
+
+ }
+
+ if (i == 0)
+ asprintf(&value, "%d %s", (int)speed, units[i]);
+ else
+ asprintf(&value, "%.1f %s", speed, units[i]);
+
+ gtk_label_set_label(stack->net_send_speed, value);
+
+ free(value);
+
+ done:
+
+ return result;
+
+}
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_BOTTOM:
+ gtk_toggle_button_set_active(stack->bottom_toggler, g_value_get_boolean(value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_BOTTOM:
+ g_value_set_boolean(value, gtk_toggle_button_get_active(stack->bottom_toggler));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MISE EN AVANT DES MESSAGES SIMPLES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* msg = simple message à faire paraître. *
+* *
+* Description : Inscrit un message simple dans la barre de statut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_display_message(GtkStatusStack *stack, const char *msg)
+{
+ if (stack->msg != NULL)
+ free(stack->msg);
+
+ if (msg != NULL)
+ stack->msg = strdup(msg);
+ else
+ stack->msg = NULL;
+
+ gtk_status_stack_show_simple_message(stack);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "default". *
+* *
+* Retour : G_SOURCE_REMOVE pour une exécution unique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_show_simple_message(gpointer data)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(data);
+
+ stack->def_source = gtk_status_stack_show_simple_message;
+
+ gtk_label_set_text(stack->def_label, stack->msg != NULL ? stack->msg : "");
+
+ gtk_stack_set_visible_child_name(stack->main, "default");
+
+ return G_SOURCE_REMOVE;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à initialiser. *
+* *
+* Description : Met en place le suivi d'informations de navigation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_navigation_info(navigation_info_t *info)
+{
+ info->segment = NULL;
+
+ info->symbol = NULL;
+
+ info->format = NULL;
+ info->details = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à libérer de la mémoire. *
+* *
+* Description : Supprime l'empreinte mémoire d'informations de navigation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void fini_navigation_info(navigation_info_t *info)
+{
+ if (info->segment != NULL)
+ free(info->segment);
+
+ if (info->symbol != NULL)
+ free(info->symbol);
+
+ if (info->format != NULL)
+ free(info->format);
+
+ if (info->details != NULL)
+ free(info->details);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* range = emplacement à mettre en valeur. *
+* segment = zone de binaire d'appartenance. *
+* symbol = éventuelle position par rapport à un symbole. *
+* format = format du binaire manipulé *
+* details = détails supplémentaires (liés à l'encodage ?) *
+* *
+* Description : Actualise les informations liées une position d'assemblage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *format, const char *details)
+{
+ navigation_info_t *info; /* Informations à constituer */
+ const vmpa2t *addr; /* Localisation de départ */
+
+ info = stack->nav_info;
+
+ if (cmp_mrange(&info->current, range) == 0)
+ goto useless;
+
+ /* Zone d'appartenance */
+
+ if (segment != NULL)
+ info->segment = strdup(segment);
+ else
+ info->segment = NULL;
+
+ /* Adresses de base */
+
+ copy_mrange(&info->current, range);
+
+ addr = get_mrange_addr(range);
+
+ vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
+
+ vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
+
+ /* Symbole concerné */
+
+ if (symbol != NULL)
+ info->symbol = strdup(symbol);
+ else
+ info->symbol = NULL;
+
+ /* Architecture & format */
+
+ info->format = strdup(format);
+
+ if (details != NULL)
+ info->details = strdup(details);
+ else
+ info->details = NULL;
+
+ /* Nettoyage et conclusion */
+
+ gtk_status_stack_show_current_location(stack);
+
+ useless:
+
+ ;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "navigation". *
+* *
+* Retour : G_SOURCE_REMOVE pour une exécution unique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_show_current_location(gpointer data)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+ navigation_info_t *info; /* Informations à constituer */
+ char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */
+
+ stack = GTK_STATUS_STACK(data);
+
+ stack->def_source = gtk_status_stack_show_current_location;
+
+ info = stack->nav_info;
+
+ /* Première partie : navigation */
+
+ gtk_label_set_text(stack->nav_segment, info->segment != NULL ? info->segment : "");
+
+ snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
+
+ gtk_label_set_text(stack->nav_phys, raw_pos);
+
+ snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
+
+ gtk_label_set_text(stack->nav_virt, raw_pos);
+
+ gtk_label_set_text(stack->nav_offset, info->symbol != NULL ? info->symbol : "");
+
+ /* Seconde partie : format & architecture */
+
+ gtk_label_set_text(stack->nav_format, info->format);
+
+ gtk_label_set_text(stack->nav_details, info->details != NULL ? info->details : "");
+
+ /* Conclusion */
+
+ gtk_stack_set_visible_child_name(stack->main, "navigation");
+
+ return G_SOURCE_REMOVE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = zone de texte visée par la procédure. *
+* icon_pos = position de l'image associée à l'entrée. *
+* stack = composant graphique de gestion des statuts. *
+* *
+* Description : Réagit à un clic sur l'icône de zoom. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GtkStatusStack *stack)
+{
+#if 0
+ GtkWidget *popup; /* Popup à faire surgir */
+ GdkRectangle rect; /* Zone précise à cibler */
+
+ popup = gtk_popover_new();
+
+ gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
+ gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
+
+ gtk_widget_show(popup);
+#endif
+}
+
+
+/* ---------------------------------------------------------------------------------- */
+/* STATUT DES SUIVIS D'ACTIVITE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à initialiser. *
+* *
+* Description : Met en place le suivi d'informations d'activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_activity_info(activity_info_t *info)
+{
+ g_mutex_init(&info->access);
+
+ info->generator = NO_ACTIVITY_ID;
+
+ info->statuses = NULL;
+ info->count = 0;
+
+ info->tag = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à libérer de la mémoire. *
+* *
+* Description : Supprime l'empreinte mémoire d'informations d'activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void fini_activity_info(activity_info_t *info)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = 0;
+
+ for (i = 0; i < info->count; i++)
+ {
+ if (info->statuses[i].message != NULL)
+ free(info->statuses[i].message);
+ }
+
+ if (info->statuses != NULL)
+ {
+ free(info->statuses);
+ info->statuses = NULL;
+ }
+
+ info->count = 0;
+
+ g_mutex_clear(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations relatives aux activités à consulter. *
+* id = identifiant de l'activité à cibler. *
+* *
+* Description : Recherche les indications de statut d'une activité donnée. *
+* *
+* Retour : Structure d'encadrement trouvée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static activity_status_t *find_activity_status_by_id(activity_info_t *info, activity_id_t id)
+{
+ activity_status_t *result; /* Statut trouvé à renvoyer */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ assert(!g_mutex_trylock(&info->access));
+
+ for (i = 0; i < info->count; i++)
+ if (info->statuses[i].id == id)
+ {
+ result = info->statuses + i;
+ break;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* msg = nouveau message de statut à copier. *
+* max = taille de la plage à parcourir. *
+* *
+* Description : Démarre le suivi d'une nouvelle activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max)
+{
+ activity_id_t result; /* Numéro unique à renvoyer */
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *new; /* Nouveau suivi d'activité */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ while (1)
+ {
+ result = ++info->generator;
+
+ if (find_activity_status_by_id(info, result) == NULL)
+ break;
+
+ }
+ while (0);
+
+ info->statuses = realloc(info->statuses, ++info->count * sizeof(activity_status_t));
+
+ new = info->statuses + info->count - 1;
+
+ /* Identifiant */
+
+ new->id = result;
+
+ /* Intitulé */
+
+ if (msg == NULL)
+ new->message = NULL;
+ else
+ new->message = strdup(msg);
+
+ /* Valeur */
+
+ new->current = 0;
+ new->max = max;
+ new->last_updated = 0;
+
+ /* Actualisation */
+
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ g_mutex_unlock(&info->access);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* id = identifiant de l'activité à cibler. *
+* msg = nouveau message de statut à copier. *
+* *
+* Description : Actualise les informations concernant une activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_activity_message(GtkStatusStack *stack, activity_id_t id, const char *msg)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+ bool msg_changed; /* Changement d'intitulé */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ /* Intitulé */
+
+ if (status->message != NULL)
+ {
+ if (msg == NULL)
+ msg_changed = true;
+ else
+ msg_changed = (strcmp(status->message, msg) != 0);
+
+ free(status->message);
+
+ }
+ else
+ msg_changed = (msg != NULL);
+
+ if (msg == NULL)
+ status->message = NULL;
+ else
+ status->message = strdup(msg);
+
+ /* On n'actualise que le sommet de la pile */
+
+ if ((status - info->statuses + 1) == info->count && msg_changed)
+ {
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ }
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* id = identifiant de l'activité à cibler. *
+* inc = nouvelle valeur pour une progression donnée. *
+* *
+* Description : Actualise la progression d'une activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+ double new; /* Nouvelle progression */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ /* Valeur */
+
+ status->current += inc;
+
+ new = (status->current * 1.0) / status->max;
+
+ /* On n'actualise que le sommet de la pile */
+
+ if ((status - info->statuses + 1) == info->count && (new - status->last_updated) > 0.1)
+ {
+ status->last_updated = new;
+
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ }
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* id = identifiant de l'activité à cibler. *
+* extra = nouvelle échéance supplémentaire des traitements. *
+* *
+* Description : Etend la portée des travaux d'une nouvelle activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_extend_activity_max(GtkStatusStack *stack, activity_id_t id, unsigned long extra)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ /* Valeur */
+
+ status->max += extra;
+
+ /* On n'actualise que le sommet de la pile */
+
+ if ((status - info->statuses + 1) == info->count)
+ {
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ }
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* *
+* Description : Met fin au suivi d'une activité donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+ bool is_last; /* Dernière position ? */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ is_last = ((status - info->statuses + 1) == info->count);
+
+ /* Suppression des données */
+
+ if (is_last)
+ {
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+ }
+
+ if (status->message != NULL)
+ free(status->message);
+
+ /* Réajustement des enregistrements */
+
+ if (!is_last)
+ memmove(status, status + 1,
+ (((info->statuses + info->count) - status) - 1) * sizeof(activity_status_t));
+
+ info->statuses = realloc(info->statuses, --info->count * sizeof(activity_status_t));
+
+ /* Bascule vers un autre affichage ou actualisation ? */
+
+ if (info->count == 0)
+ {
+ info->tag = 0;
+ gtk_status_stack_reset_to_default(stack);
+ }
+ else if (is_last)
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "activité". *
+* *
+* Retour : G_SOURCE_REMOVE pour une exécution unique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_show_current_activity(gpointer data)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *last; /* Dernier statut à traiter */
+
+ stack = GTK_STATUS_STACK(data);
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ if (!g_source_is_destroyed(g_main_current_source()))
+ {
+ if (info->count > 0)
+ {
+ last = &info->statuses[info->count - 1];
+
+ gtk_label_set_text(stack->activity_message, last->message);
+
+ gtk_progress_bar_set_fraction(stack->activity_progress, (last->current * 1.0) / last->max);
+
+ gtk_stack_set_visible_child_name(stack->main, "activity");
+
+ }
+
+ info->tag = 0;
+
+ }
+
+ g_mutex_unlock(&info->access);
+
+ return G_SOURCE_REMOVE;
+
+}
diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/statusstack.h
index f419014..96d008c 100644
--- a/src/gtkext/gtkstatusstack.h
+++ b/src/gtkext/statusstack.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkstatusstack.h - prototypes pour un empilement d'informations de statut
+ * statusstack.h - prototypes pour l'empilement d'informations de statut
*
- * Copyright (C) 2015-2019 Cyrille Bagard
+ * Copyright (C) 2015-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,40 +21,39 @@
*/
-#ifndef _GTKEXT_GTKSTATUSSTACK_H
-#define _GTKEXT_GTKSTATUSSTACK_H
+#ifndef _GTKEXT_STATUSSTACK_H
+#define _GTKEXT_STATUSSTACK_H
#include <gtk/gtk.h>
#include "../arch/vmpa.h"
+#include "../glibext/helpers.h"
-/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
+/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */
-#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type())
-#define GTK_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_STATUS_STACK, GtkStatusStack))
-#define GTK_STATUS_STACK_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, GTK_TYPE_STATUS_STACK, GtkStatusStackClass))
-#define GTK_IS_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK))
-#define GTK_IS_STATUS_STACK_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK))
-#define GTK_STATUS_STACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_STATUS_STACK, GtkStatusStackClass))
+#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type())
+DECLARE_GTYPE(GtkStatusStack, gtk_status_stack, GTK, STATUS_STACK);
-/* Abstration d'une gestion de barre de statut (instance) */
-typedef struct _GtkStatusStack GtkStatusStack;
-/* Abstration d'une gestion de barre de statut (classe) */
-typedef struct _GtkStatusStackClass GtkStatusStackClass;
+/* Crée une nouvelle instance de barre de statut. */
+GtkStatusStack *gtk_status_stack_new(void);
+/* Réinitialise la barre de statut à son stade par défaut. */
+void gtk_status_stack_reset_to_default(GtkStatusStack *);
-/* Détermine le type de la barre de statut améliorée. */
-GType gtk_status_stack_get_type(void);
-/* Crée une nouvelle instance de barre de statut. */
-GtkStatusStack *gtk_status_stack_new(void);
+
+/* ----------------------- MISE EN AVANT DES MESSAGES SIMPLES ----------------------- */
+
+
+/* Inscrit un message simple dans la barre de statut. */
+void gtk_status_stack_display_message(GtkStatusStack *, const char *);
@@ -62,10 +61,7 @@ GtkStatusStack *gtk_status_stack_new(void);
/* Actualise les informations liées une position d'assemblage. */
-void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *);
-
-/* Réinitialise les informations associées une position. */
-void gtk_status_stack_reset_current_location(GtkStatusStack *);
+void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *, const char *);
@@ -82,18 +78,18 @@ typedef unsigned long activity_id_t;
/* Démarre le suivi d'une nouvelle activité. */
activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long);
-/* Etend la portée des travaux d'une nouvelle activité. */
-void gtk_status_stack_extend_activity(GtkStatusStack *, activity_id_t, unsigned long);
-
/* Actualise les informations concernant une activité. */
-void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *);
+void gtk_status_stack_update_activity_message(GtkStatusStack *, activity_id_t, const char *);
/* Actualise la progression d'une activité. */
void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, unsigned long);
+/* Etend la portée des travaux d'une nouvelle activité. */
+void gtk_status_stack_extend_activity_max(GtkStatusStack *, activity_id_t, unsigned long);
+
/* Met fin au suivi d'une activité donnée. */
void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t);
-#endif /* _GTKEXT_GTKSTATUSSTACK_H */
+#endif /* _GTKEXT_STATUSSTACK_H */
diff --git a/src/gtkext/statusstack.ui b/src/gtkext/statusstack.ui
new file mode 100644
index 0000000..0b7cd6d
--- /dev/null
+++ b/src/gtkext/statusstack.ui
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkStatusStack" parent="GtkBox">
+
+ <!--property name="show-bottom" bind-source="bottom_toggler" bind-property="active" bind-flags="bidirectional|sync-create"/-->
+
+ <child>
+ <object class="GtkStack" id="main">
+ <property name="margin-start">8</property>
+ <property name="margin-end">8</property>
+ <property name="hexpand">true</property>
+
+ <!-- Vide par défaut -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">default</property>
+ <property name="child">
+
+ <object class="GtkLabel" id="def_label">
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">baseline</property>
+ <property name="xalign">0</property>
+ <property name="label"></property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <!-- Informations pendant une navigation dans du contenu -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">navigation</property>
+ <property name="child">
+
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+
+ <!-- Première partie : navigation -->
+
+ <child>
+ <object class="GtkLabel" id="nav_segment">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_phys">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_virt">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_offset">
+ <property name="xalign">0</property>
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <!-- Seconde partie : architecture -->
+
+ <child>
+ <object class="GtkLabel" id="nav_format">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_details">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <!-- Troisième partie : affichage -->
+
+ <child>
+ <object class="GtkEntry" id="zoom">
+ <property name="secondary-icon-name">go-up-symbolic</property>
+ <signal name="icon-press" handler="gtk_status_stack_on_zoom_icon_press"/>
+ </object>
+ </child>
+
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <!-- Informations liées à une activité en cours -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">activity</property>
+ <property name="child">
+
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+
+ <child>
+ <object class="GtkLabel" id="activity_message">
+ <property name="xalign">0</property>
+ <property name="margin-end">8</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkProgressBar" id="activity_progress">
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="fraction">0</property>
+ </object>
+ </child>
+
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <property name="visible-child-name">default</property>
+ </object>
+ </child>
+
+ <!-- Tronc commun -->
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkToggleButton" id="lock_update">
+ <property name="sensitive">false</property>
+ <property name="has-frame">false</property>
+ <property name="icon-name">nolock-symbolic</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage">
+ <property name="margin-start">8</property>
+ <property name="icon-name">pan-down-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="net_recv_speed">
+ <property name="margin-start">8</property>
+ <property name="margin-end">8</property>
+ <property name="xalign">0</property>
+ <property name="label">0 b/s</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">pan-up-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="net_send_speed">
+ <property name="margin-start">8</property>
+ <property name="margin-end">8</property>
+ <property name="xalign">0</property>
+ <property name="label">0 b/s</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkToggleButton" id="bottom_toggler">
+ <property name="has-frame">false</property>
+ <property name="icon-name">dock-station-bottom-symbolic</property>
+ <property name="action-name">win.toggle-bottom</property>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/tiledgrid.c b/src/gtkext/tiledgrid.c
deleted file mode 100644
index 22b2680..0000000
--- a/src/gtkext/tiledgrid.c
+++ /dev/null
@@ -1,1143 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * tiledgrid.c - composant d'affichage avec des chemins vers les composants contenus
- *
- * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "tiledgrid.h"
-
-
-#include <assert.h>
-#include <ctype.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include "../core/logs.h"
-
-
-
-/* -------------------------- GESTION DES TUILES AFFICHEES -------------------------- */
-
-
-/* Informations concernant une tuile */
-typedef struct _grid_tile_t
-{
- struct _grid_tile_t *parent; /* Tuile parente */
-
- GtkWidget *widget; /* Support d'affichage */
-
- char *path; /* Chemin d'accès */
-
- struct _grid_tile_t *children[2]; /* Tuiles encastrées ou 2xNULL */
-
-} grid_tile_t;
-
-
-#define IS_LEAF_TILE(t) \
- ({ \
- bool __result; \
- __result = GTK_IS_DOCK_STATION((t)->widget); \
- assert(__result || GTK_IS_PANED((t)->widget)); \
- __result; \
- })
-
-
-/* Valide un chemin d'accès à une tuile. */
-static bool is_valid_tile_path(const char *);
-
-/* Crée une tuile finale d'affichage de panneaux. */
-static grid_tile_t *create_leaf_tile(const char *, GtkTiledGrid *);
-
-/* Crée une tuile intermédiaire d'affichage de panneaux. */
-static grid_tile_t *create_inter_tile(grid_tile_t *, bool, grid_tile_t *, grid_tile_t *);
-
-/* Supprime une tuile de la mémoire. */
-static void delete_tile(grid_tile_t *);
-
-/* Calcule la taille comme entre un chemin et celui d'une tuile. */
-static size_t compute_tile_score(const grid_tile_t *, const char *);
-
-/* Indique la tuile adaptée pour un chemin donné. */
-static grid_tile_t *find_suitable_tile(grid_tile_t **, const char *, GtkTiledGrid *);
-
-/* Découpe une tuile pour y insérer une zone. */
-static grid_tile_t *split_tile(grid_tile_t **, const char *, char, GtkTiledGrid *);
-
-/* Tente de mettre la main sur une station d'accueil. */
-static grid_tile_t *find_tile_for_widget(grid_tile_t *, GtkWidget *);
-
-/* Retire une moitié de tuile vide au plein profit de l'autre. */
-static void collapse_tile(grid_tile_t *, grid_tile_t *);
-
-
-
-/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
-
-
-/* Conteneur pour un affichage en tuiles nommées (instance) */
-struct _GtkTiledGrid
-{
- GtkBin parent; /* A laisser en premier */
-
- grid_tile_t *tiles; /* Tuiles représentées */
-
- GPanelItem *def_panel; /* Panneau principal par défaut*/
-
-};
-
-/* Conteneur pour un affichage en tuiles nommées (classe) */
-struct _GtkTiledGridClass
-{
- GtkBinClass parent; /* A laisser en premier */
-
- /* Signaux */
-
- void (* station_created) (GtkTiledGrid *, GtkDockStation *, gpointer);
-
-};
-
-
-/* Initialise la classe des conteneurs d'affichage en tuiles. */
-static void gtk_tiled_grid_class_init(GtkTiledGridClass *);
-
-/* Initialise une instance de conteneur d'affichage en tuiles. */
-static void gtk_tiled_grid_init(GtkTiledGrid *);
-
-/* Supprime toutes les références externes. */
-static void gtk_tiled_grid_dispose(GtkTiledGrid *);
-
-/* Procède à la libération totale de la mémoire. */
-static void gtk_tiled_grid_finalize(GtkTiledGrid *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES TUILES AFFICHEES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : path = chemin destiné à sélectionner une tuile. *
-* *
-* Description : Valide un chemin d'accès à une tuile. *
-* *
-* Retour : true si le chemin est utilisable, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool is_valid_tile_path(const char *path)
-{
- bool result; /* Bilan à retourner */
- size_t len; /* Taille du chemin */
- size_t i; /* Boucle de parcours */
- char c; /* Caractère de chemin analysé */
-
- /**
- * M[NESWnesw]*
- */
-
- len = strlen(path);
-
- result = (len >= 1);
-
- if (result)
- result = (path[0] == 'M');
-
- for (i = 1; i < len && result; i++)
- {
- c = path[i];
-
- if (c == '\0')
- break;
-
- result = (c == 'N' || c == 'n'
- || c == 'E' || c == 'e'
- || c == 'S' || c == 's'
- || c == 'W' || c == 'w');
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : path = chemin d'accès à la future tuile. *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à manipuler. *
-* *
-* Description : Crée une tuile finale d'affichage de panneaux. *
-* *
-* Retour : Structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *create_leaf_tile(const char *path, GtkTiledGrid *tgrid)
-{
- grid_tile_t *result; /* Structure à retourner */
-
- result = (grid_tile_t *)malloc(sizeof(grid_tile_t));
-
- result->parent = NULL;
-
- result->widget = gtk_dock_station_new();
- gtk_widget_show(result->widget);
-
- result->path = strdup(path);
-
- result->children[0] = NULL;
- result->children[1] = NULL;
-
- g_signal_emit_by_name(tgrid, "station-created", result->widget);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = tuile parente ou NULL si aucune. *
-* horiz = indique le type d'orientation désiré. *
-* first = première tuile à intégrer. *
-* second = seconde tuile à intégrer. *
-* *
-* Description : Crée une tuile intermédiaire d'affichage de panneaux. *
-* *
-* Retour : Structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *create_inter_tile(grid_tile_t *parent, bool horiz, grid_tile_t *first, grid_tile_t *second)
-{
- grid_tile_t *result; /* Structure à retourner */
- GtkWidget *container; /* Conteneur à vider */
-
- result = (grid_tile_t *)malloc(sizeof(grid_tile_t));
-
- result->parent = parent;
-
- if (horiz)
- result->widget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
- else
- result->widget = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
-
- gtk_widget_show(result->widget);
-
- result->path = NULL;
-
- result->children[0] = first;
- result->children[1] = second;
-
- /* Changement de propriétaire */
-
- container = gtk_widget_get_parent(first->widget);
-
- if (container != NULL)
- gtk_container_remove(GTK_CONTAINER(container), first->widget);
-
- g_object_ref(G_OBJECT(first->widget));
- gtk_paned_pack1(GTK_PANED(result->widget), first->widget, TRUE, FALSE);
-
- container = gtk_widget_get_parent(second->widget);
-
- if (container != NULL)
- gtk_container_remove(GTK_CONTAINER(container), second->widget);
-
- g_object_ref(G_OBJECT(second->widget));
- gtk_paned_pack2(GTK_PANED(result->widget), second->widget, TRUE, FALSE);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à supprimer. *
-* *
-* Description : Supprime une tuile de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void delete_tile(grid_tile_t *tile)
-{
- if (!IS_LEAF_TILE(tile))
- {
- delete_tile(tile->children[0]);
- delete_tile(tile->children[1]);
- }
-
- else
- free(tile->path);
-
- g_object_unref(G_OBJECT(tile->widget));
-
- free(tile);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à analyser. *
-* path = chemin final complet recherché. *
-* *
-* Description : Calcule la taille comme entre un chemin et celui d'une tuile.*
-* *
-* Retour : Quantité de caractères communs. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static size_t compute_tile_score(const grid_tile_t *tile, const char *path)
-{
- size_t result; /* Nombre de points à renvoyer */
- size_t max; /* Taille du chemin de la tuile*/
- size_t i; /* Boucle de parcours */
- size_t score_0; /* Score du sous-élément #1 */
- size_t score_1; /* Score du sous-élément #2 */
-
- if (IS_LEAF_TILE(tile))
- {
- max = strlen(tile->path);
-
- if (strlen(path) < max)
- result = 0;
-
- else
- {
- result = 0;
-
- for (i = 0; i < max; i++)
- {
- if (tolower((unsigned char)tile->path[i]) == tolower((unsigned char)path[i]))
- result++;
- else
- break;
- }
-
- }
-
- }
- else
- {
- score_0 = compute_tile_score(tile->children[0], path);
- score_1 = compute_tile_score(tile->children[1], path);
-
- result = score_0 > score_1 ? score_0 : score_1;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile ou NULL si aucune. [OUT] *
-* path = chemin d'accès à la tuile visée. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
-* *
-* Description : Indique la tuile adaptée pour un chemin donné. *
-* *
-* Retour : Structure d'acceuil à disposition. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *find_suitable_tile(grid_tile_t **tile, const char *path, GtkTiledGrid *tgrid)
-{
- grid_tile_t *result; /* Structure à renvoyer */
- size_t best_len; /* Taille du chemin associé */
- size_t score_0; /* Score du sous-élément #1 */
- size_t score_1; /* Score du sous-élément #2 */
- char *sub_path; /* Nouvelle tentative d'accès */
- grid_tile_t **best; /* Direction à prendre */
- unsigned char next; /* Prochaine étape */
-
- /* Cas d'école : appel initial */
- if (*tile == NULL)
- {
- assert(path[0] == 'M' && path[1] == '\0');
-
- result = create_leaf_tile("M", tgrid);
- *tile = result;
-
- }
-
- else
- {
- if (IS_LEAF_TILE(*tile))
- {
- best_len = compute_tile_score(*tile, path);
-
- assert(best_len > 0);
-
- if (path[best_len] == '\0')
- result = *tile;
-
- else
- result = split_tile(tile, path, path[best_len], tgrid);
-
- }
-
- else
- {
- score_0 = compute_tile_score((*tile)->children[0], path);
- score_1 = compute_tile_score((*tile)->children[1], path);
-
- assert(score_0 > 0 || score_0 > 0);
-
- if (score_0 == score_1)
- {
- sub_path = strndup(path, score_0);
-
- score_0 = compute_tile_score((*tile)->children[0], sub_path);
- score_1 = compute_tile_score((*tile)->children[1], sub_path);
-
- free(sub_path);
-
- }
-
- if (score_0 == score_1)
- result = split_tile(tile, path, path[score_0], tgrid);
-
- else
- {
- if (score_0 > score_1)
- {
- best = &(*tile)->children[0];
- best_len = score_0;
- }
- else
- {
- best = &(*tile)->children[1];
- best_len = score_1;
- }
-
- /**
- * Si on vient de tomber une feuille, trois cas de figure :
- * - soit c'est elle qui est visée.
- * - soit on veut la diviser.
- * - soit on veut la diviser en englobant ses voisines.
- */
-
- if (IS_LEAF_TILE(*best))
- {
- assert(best_len <= strlen(path));
-
- next = path[best_len];
-
- /* Premier cas */
- if (next == '\0')
- result = *best;
-
- else
- {
- /* Second cas */
- if (islower(next))
- result = find_suitable_tile(best, path, tgrid);
-
- /* Troisième cas */
- else
- result = split_tile(tile, path, next, tgrid);
-
- }
-
- }
-
- else
- result = find_suitable_tile(best, path, tgrid);
-
- }
-
- }
-
- }
-
- assert(IS_LEAF_TILE(result));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à découper en deux. [OUT] *
-* path = chemin d'accès à la future tuile. *
-* endpoint = désignation de la zone représentée. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
-* *
-* Description : Découpe une tuile pour y insérer une zone. *
-* *
-* Retour : Structure fille mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *split_tile(grid_tile_t **tile, const char *path, char endpoint, GtkTiledGrid *tgrid)
-{
- grid_tile_t *result; /* Création à retourner */
- GtkWidget *container; /* Conteneur à vider */
- grid_tile_t *new; /* Nouvelle tuile intermédiaire*/
-
- container = gtk_widget_get_parent((*tile)->widget);
-
- /* Création */
-
- result = create_leaf_tile(path, tgrid);
-
- /* Encapsulation */
-
- switch (endpoint)
- {
- case 'N':
- case 'n':
- new = create_inter_tile((*tile)->parent, false, result, *tile);
- break;
-
- case 'E':
- case 'e':
- new = create_inter_tile((*tile)->parent, true, *tile, result);
- break;
-
- case 'S':
- case 's':
- new = create_inter_tile((*tile)->parent, false, *tile, result);
- break;
-
- case 'W':
- case 'w':
- new = create_inter_tile((*tile)->parent, true, result, *tile);
- break;
-
- default:
- assert(false);
- new = NULL;
- break;
-
- }
-
- /* Connexions */
-
- *tile = new;
-
- result->parent = new;
-
- if (container != NULL)
- {
- g_object_ref(G_OBJECT(new->widget));
- gtk_container_add(GTK_CONTAINER(container), new->widget);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile parente, prochaine victime de promotion. *
-* side = côté de tuile amené à disparaître. *
-* *
-* Description : Retire une moitié de tuile vide au plein profit de l'autre. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void collapse_tile(grid_tile_t *tile, grid_tile_t *side)
-{
- grid_tile_t *promoted; /* Tuile à faire remonter */
- GtkWidget *container; /* Conteneur à vider */
-
- assert(!IS_LEAF_TILE(tile));
-
- /* Sélection du remplaçant */
-
- if (side == tile->children[0])
- promoted = tile->children[1];
- else
- promoted = tile->children[0];
-
- /* Etablissement d'une place nette */
-
- gtk_container_remove(GTK_CONTAINER(tile->widget), promoted->widget);
-
- container = gtk_widget_get_parent(tile->widget);
- gtk_container_remove(GTK_CONTAINER(container), tile->widget);
-
- delete_tile(side);
-
- /* Promotion effective */
-
- tile->widget = promoted->widget;
-
- tile->path = promoted->path;
-
- tile->children[0] = promoted->children[0];
- tile->children[1] = promoted->children[1];
-
- g_object_ref(G_OBJECT(promoted->widget));
- gtk_container_add(GTK_CONTAINER(container), tile->widget);
-
- free(promoted);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = point de départ des recherches locales. *
-* widget = composant graphique à retrouver. *
-* *
-* Description : Tente de mettre la main sur une station d'accueil. *
-* *
-* Retour : Eventuelle tuile trouvée ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *find_tile_for_widget(grid_tile_t *tile, GtkWidget *widget)
-{
- grid_tile_t *result; /* Tuile à retourner */
-
- if (IS_LEAF_TILE(tile))
- result = tile->widget == widget ? tile : NULL;
-
- else
- {
- result = find_tile_for_widget(tile->children[0], widget);
-
- if (result == NULL)
- result = find_tile_for_widget(tile->children[1], widget);
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* INTERFACE DU COMPOSANT GTK */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type du conteneur d'affichage en tuiles nommées. */
-G_DEFINE_TYPE(GtkTiledGrid, gtk_tiled_grid, GTK_TYPE_BIN)
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe GTK à initialiser. *
-* *
-* Description : Initialise la classe des conteneurs d'affichage en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_class_init(GtkTiledGridClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tiled_grid_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_tiled_grid_finalize;
-
- g_signal_new("station-created",
- GTK_TYPE_TILED_GRID,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkTiledGridClass, station_created),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_DOCK_STATION);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = instance GTK à initialiser. *
-* *
-* Description : Initialise une instance de conteneur d'affichage en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_init(GtkTiledGrid *tgrid)
-{
- tgrid->tiles = NULL;
-
- tgrid->def_panel = NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_dispose(GtkTiledGrid *tgrid)
-{
- if (tgrid->tiles != NULL)
- {
- delete_tile(tgrid->tiles);
- tgrid->tiles = NULL;
- }
-
- g_clear_object(&tgrid->def_panel);
-
- G_OBJECT_CLASS(gtk_tiled_grid_parent_class)->dispose(G_OBJECT(tgrid));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_finalize(GtkTiledGrid *tgrid)
-{
- G_OBJECT_CLASS(gtk_tiled_grid_parent_class)->finalize(G_OBJECT(tgrid));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée une nouvelle instance de conteneur avec tuiles. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkWidget *gtk_tiled_grid_new(void)
-{
- return g_object_new(GTK_TYPE_TILED_GRID, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* *
-* Description : Donne le panneau fourni par défaut pour la zone principale. *
-* *
-* Retour : Panneau d'affichage par défault ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *tgrid)
-{
- GPanelItem *result; /* Panneau à retourner */
-
- result = tgrid->def_panel;
-
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage par défault ou NULL. *
-* *
-* Description : Fournit le panneau par défaut pour la zone principale. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *tgrid, GPanelItem *panel)
-{
- GtkWidget *widget; /* Composant GTK à retirer */
- GtkWidget *parent; /* Conteneur à vider */
- grid_tile_t *tile; /* Première tuile d'accueil */
-
- if (tgrid->def_panel != NULL)
- {
- widget = gtk_dockable_build_widget(GTK_DOCKABLE(tgrid->def_panel));
-
- parent = gtk_widget_get_parent(widget);
-
- if (parent != NULL)
- gtk_container_remove(GTK_CONTAINER(parent), widget);
-
- g_object_unref(G_OBJECT(widget));
-
- g_object_unref(G_OBJECT(tgrid->def_panel));
-
- }
-
- tgrid->def_panel = panel;
-
- if (panel != NULL)
- {
- g_object_ref(G_OBJECT(panel));
-
- if (tgrid->tiles == NULL)
- gtk_tiled_grid_add(tgrid, panel);
-
- else
- {
- tile = find_suitable_tile(&tgrid->tiles, "M", tgrid);
-
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(tile->widget)) == 0)
- gtk_tiled_grid_add(tgrid, panel);
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage à intégrer. *
-* *
-* Description : Incorpore un nouveau panneau dans le conteneur en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_add(GtkTiledGrid *tgrid, GPanelItem *panel)
-{
- char *path; /* Chemin d'accès */
- char *name; /* Nom à donner à l'onglet */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- path = gtk_panel_item_class_get_path(G_PANEL_ITEM_GET_CLASS(panel));
-
- if (!is_valid_tile_path(path))
- {
- name = gtk_dockable_get_name(GTK_DOCKABLE(panel));
- log_variadic_message(LMT_ERROR, _("Invalid path '%s' for panel '%s'"), path, name);
- free(name);
- }
-
- else
- {
- tile = find_suitable_tile(&tgrid->tiles, path, tgrid);
- assert(tile != NULL);
-
- gtk_dock_station_add_dockable(GTK_DOCK_STATION(tile->widget), GTK_DOCKABLE(panel));
-
- g_panel_item_set_dock_at_startup(panel, true);
-
- /* Si c'est la toute première fois... */
- if (gtk_widget_get_parent(tile->widget) == NULL)
- {
- assert(tile == tgrid->tiles);
- assert(tile->path[0] == 'M' && tile->path[1] == '\0');
- g_object_ref(G_OBJECT(tile->widget));
- gtk_container_add(GTK_CONTAINER(tgrid), tile->widget);
- }
-
- /* Si on n'a plus besoin du panneau par défaut */
- if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0')
- {
- /* Si ce n'est pas le panneau qu'on vient de rajouter...*/
- if (panel != tgrid->def_panel)
- {
- /* Enfin : si ce panneau par défaut est réellement en place */
- if (g_panel_item_is_docked(tgrid->def_panel))
- gtk_tiled_grid_remove(tgrid, tgrid->def_panel);
-
- }
-
- }
-
- }
-
- free(path);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage à supprimer. *
-* *
-* Description : Retire un panneau dans le conteneur en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_remove(GtkTiledGrid *tgrid, GPanelItem *panel)
-{
- GtkWidget *station; /* Support courant */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- assert(g_panel_item_is_docked(panel));
-
- gtk_dockable_decompose(GTK_DOCKABLE(panel), &station);
-
- tile = find_tile_for_widget(tgrid->tiles, station);
- assert(tile != NULL);
-
- gtk_dock_station_remove_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(panel));
-
- g_panel_item_set_dock_at_startup(panel, false);
-
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(station)) == 0)
- {
- /* Si le panneau par défaut devient nécessaire */
- if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0')
- gtk_tiled_grid_add(tgrid, tgrid->def_panel);
-
- else
- {
- /* La racine est concernée ! */
- if (tile->parent == NULL)
- {
- assert(tile == tgrid->tiles);
-
- g_object_ref(G_OBJECT(tile->widget));
- gtk_container_remove(GTK_CONTAINER(tgrid), tile->widget);
-
- delete_tile(tile);
- tgrid->tiles = NULL;
-
- }
-
- else
- collapse_tile(tile->parent, tile);
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* station = station d'accueil à retrouver. *
-* *
-* Description : Indique le chemin correspondant à une station intégrée. *
-* *
-* Retour : Copie de chemin trouvé, à libérer ensuite, ou NULL si échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-char *gtk_tiled_grid_get_path_for_station(const GtkTiledGrid *tgrid, GtkDockStation *station)
-{
- char *result; /* Chemin d'accès à renvoyer */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- tile = find_tile_for_widget(tgrid->tiles, GTK_WIDGET(station));
-
- if (tile == NULL)
- result = NULL;
-
- else
- result = strdup(tile->path);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à mettre à jour. *
-* config = configuration à consulter. *
-* *
-* Description : Replace les positions des séparateurs de tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_restore_positions(const GtkTiledGrid *tgrid, GGenConfig *config)
-{
-
- void visit_tiles_for_restoring(grid_tile_t *tile, const char *vpath)
- {
- GtkOrientation orientation; /* Direction de la tuile */
- char hint; /* Inutile donc indispensable */
- char *key; /* Clef d'accès à un paramètre */
- gint position; /* Nouvelle position de barre */
- size_t i; /* Boucle de parcours */
- char *child_key; /* Clef d'accès des suivants */
-
- if (!IS_LEAF_TILE(tile))
- {
- orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget));
-
- hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v';
-
- asprintf(&key, "%s%c", vpath, hint);
-
- if (g_generic_config_get_value(config, key, &position))
- gtk_paned_set_position(GTK_PANED(tile->widget), position);
-
- for (i = 0; i < 2; i++)
- {
- asprintf(&child_key, "%s%zu", key, i);
-
- visit_tiles_for_restoring(tile->children[i], child_key);
-
- free(child_key);
-
- }
-
- free(key);
-
- }
-
- }
-
-
- visit_tiles_for_restoring(tgrid->tiles, "gui.panels.positions.R");
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* config = configuration à mettre à jour. *
-* *
-* Description : Sauvegarde les positions des séparateurs de tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_save_positions(const GtkTiledGrid *tgrid, GGenConfig *config)
-{
-
- void visit_tiles_for_saving(grid_tile_t *tile, const char *vpath)
- {
- GtkOrientation orientation; /* Direction de la tuile */
- char hint; /* Inutile donc indispensable */
- char *key; /* Clef d'accès à un paramètre */
- gint position; /* Nouvelle position de barre */
- size_t i; /* Boucle de parcours */
- char *child_key; /* Clef d'accès des suivants */
-
- if (!IS_LEAF_TILE(tile))
- {
- orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget));
-
- hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v';
-
- asprintf(&key, "%s%c", vpath, hint);
-
- position = gtk_paned_get_position(GTK_PANED(tile->widget));
- g_generic_config_create_or_udpdate_param(config, key, CPT_INTEGER, -1, position);
-
- for (i = 0; i < 2; i++)
- {
- asprintf(&child_key, "%s%zu", key, i);
-
- visit_tiles_for_saving(tile->children[i], child_key);
-
- free(child_key);
-
- }
-
- free(key);
-
- }
-
- }
-
-
- visit_tiles_for_saving(tgrid->tiles, "gui.panels.positions.R");
-
-}
diff --git a/src/gtkext/tweak-int.h b/src/gtkext/tweak-int.h
new file mode 100644
index 0000000..0d2c213
--- /dev/null
+++ b/src/gtkext/tweak-int.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak-int.h - définitions internes pour une section d'éléments à paramétrer
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_TWEAK_INT_H
+#define _GTKEXT_TWEAK_INT_H
+
+
+#include "tweak.h"
+
+
+
+/* Section de paramétrage pour liste d'éléments à configurer (instance) */
+struct _GtkTweakSection
+{
+ GtkListBoxRow parent; /* A laisser en premier */
+
+ GtkImage *icon; /* Eventuelle image */
+ GtkLabel *label; /* Etiquette associée */
+ GtkWidget *next; /* Eventuelle progression */
+
+ char *category; /* Groupe de rassemblement */
+
+ union
+ {
+ GType panel; /* Accès à la page de config. */
+ char *sub; /* Sous-ensemble à presenter */
+ };
+ bool has_sub_section; /* Choix du champ valide */
+
+};
+
+/* Section de paramétrage pour liste d'éléments à configurer (classe) */
+struct _GtkTweakSectionClass
+{
+ GtkListBoxRowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une nouvelle section de configuration. */
+bool gtk_tweak_section_create(GtkTweakSection *, const tweak_info_t *);
+
+
+
+#endif /* _GTKEXT_TWEAK_INT_H */
diff --git a/src/gtkext/tweak.c b/src/gtkext/tweak.c
new file mode 100644
index 0000000..b03cf17
--- /dev/null
+++ b/src/gtkext/tweak.c
@@ -0,0 +1,319 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak.c - section d'éléments à paramétrer
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tweak.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "helpers.h"
+#include "tweak-int.h"
+
+
+
+/* Initialise la classe des sections d'éléments paramétrables. */
+static void gtk_tweak_section_class_init(GtkTweakSectionClass *);
+
+/* Initialise une instance de section d'éléments paramétrables. */
+static void gtk_tweak_section_init(GtkTweakSection *);
+
+/* Supprime toutes les références externes. */
+static void gtk_tweak_section_dispose(GtkTweakSection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_tweak_section_finalize(GtkTweakSection *);
+
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkTweakSection, gtk_tweak_section, GTK_TYPE_LIST_BOX_ROW);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des sections d'éléments paramétrables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_class_init(GtkTweakSectionClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tweak_section_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_tweak_section_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/tweak.ui");
+
+ gtk_widget_class_bind_template_child(widget, GtkTweakSection, icon);
+ gtk_widget_class_bind_template_child(widget, GtkTweakSection, label);
+ gtk_widget_class_bind_template_child(widget, GtkTweakSection, next);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de section d'éléments paramétrables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_init(GtkTweakSection *section)
+{
+ gtk_widget_init_template(GTK_WIDGET(section));
+
+ section->category = NULL;
+
+ section->sub = NULL;
+ section->has_sub_section = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_dispose(GtkTweakSection *section)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(section), GTK_TYPE_TWEAK_SECTION);
+
+ G_OBJECT_CLASS(gtk_tweak_section_parent_class)->dispose(G_OBJECT(section));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_finalize(GtkTweakSection *section)
+{
+ if (section->category != NULL)
+ free(section->category);
+
+ if (section->has_sub_section && section->sub != NULL)
+ free(section->sub);
+
+ G_OBJECT_CLASS(gtk_tweak_section_parent_class)->finalize(G_OBJECT(section));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations associées à la section. *
+* *
+* Description : Crée une nouvelle section de configuration. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkTweakSection *gtk_tweak_section_new(const tweak_info_t *info)
+{
+ GtkTweakSection *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_TWEAK_SECTION, NULL);
+
+ if (!gtk_tweak_section_create(result, info))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à initialiser pleinement. *
+* info = informations associées à la section. *
+* *
+* Description : Met en place une nouvelle section de configuration. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_tweak_section_create(GtkTweakSection *section, const tweak_info_t *info)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ gtk_image_set_from_icon_name(section->icon, info->image);
+ gtk_label_set_label(section->label, info->label);
+
+ gtk_widget_set_visible(section->next, info->has_sub_section);
+
+ section->category = strdup(info->category);
+
+ if (info->has_sub_section)
+ {
+ section->sub = strdup(info->sub);
+ section->has_sub_section = true;
+ }
+ else
+ {
+ section->panel = info->panel;
+ section->has_sub_section = false;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Fournit l'étiquette associée à une section de configuration. *
+* *
+* Retour : Désignation humaine de la section. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *gtk_tweak_section_get_label(const GtkTweakSection *section)
+{
+ const char *result; /* Texte à retourner */
+
+ result = gtk_label_get_text(section->label);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Indique si la section renvoie vers une sous-section. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_tweak_section_has_sub_section(const GtkTweakSection *section)
+{
+ bool result; /* Statut à retourner */
+
+ result = section->has_sub_section;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Fournit le type d'un éventuel panneau de configuration lié. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GType gtk_tweak_section_get_panel(const GtkTweakSection *section)
+{
+ GType result; /* Type d'objet à retourner */
+
+ assert(!section->has_sub_section);
+
+ result = section->panel;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Fournit la désignation d'une éventuelle sous-section liée. *
+* *
+* Retour : Désignation associée à la sous-section. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *gtk_tweak_section_get_sub_section(const GtkTweakSection *section)
+{
+ const char *result; /* Désignation à renvoyer */
+
+ assert(section->has_sub_section);
+
+ result = section->sub;
+
+ return result;
+
+}
diff --git a/src/gtkext/tweak.h b/src/gtkext/tweak.h
new file mode 100644
index 0000000..8c44844
--- /dev/null
+++ b/src/gtkext/tweak.h
@@ -0,0 +1,90 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak.h - prototypes pour pour une section d'éléments à paramétrer
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_TWEAK_H
+#define _GTKEXT_TWEAK_H
+
+
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+/* Définition d'une section de configuration */
+typedef struct _tweak_info_t
+{
+ const char *parent; /* Ensemble d'appartenance */
+
+ const char *category; /* Groupe de rassemblement */
+
+ const char *image; /* Eventuelle image associée */
+ const char *key; /* Désignation de la section */
+ const char *label; /* Désignation humaine */
+
+ union
+ {
+ GType panel; /* Accès à la page de config. */
+ const char *sub; /* Sous-ensemble à presenter */
+ };
+ bool has_sub_section; /* Choix du champ valide */
+
+} tweak_info_t;
+
+
+#define TWEAK_SIMPLE_DEF(p, c, i, k, l, t) \
+ { \
+ .parent = p, \
+ .category = c, \
+ .image = i, \
+ .key = k, \
+ .label = l, \
+ .panel = t, \
+ .has_sub_section = false, \
+ }
+
+#define GTK_TYPE_TWEAK_SECTION (gtk_tweak_section_get_type())
+
+DECLARE_GTYPE(GtkTweakSection, gtk_tweak_section, GTK, TWEAK_SECTION);
+
+
+/* Crée une nouvelle section de configuration. */
+GtkTweakSection *gtk_tweak_section_new(const tweak_info_t *);
+
+/* Fournit l'étiquette associée à une section de configuration. */
+const char *gtk_tweak_section_get_label(const GtkTweakSection *);
+
+/* Indique si la section renvoie vers une sous-section. */
+bool gtk_tweak_section_has_sub_section(const GtkTweakSection *);
+
+/* Fournit le type d'un éventuel panneau de configuration lié. */
+GType gtk_tweak_section_get_panel(const GtkTweakSection *);
+
+/* Fournit la désignation d'une éventuelle sous-section liée. */
+const char *gtk_tweak_section_get_sub_section(const GtkTweakSection *);
+
+
+
+#endif /* _GTKEXT_TWEAK_H */
diff --git a/src/gtkext/tweak.ui b/src/gtkext/tweak.ui
new file mode 100644
index 0000000..576e25e
--- /dev/null
+++ b/src/gtkext/tweak.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkTweakSection" parent="GtkListBoxRow">
+
+ <property name="child">
+
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="margin-top">14</property>
+ <property name="margin-bottom">14</property>
+
+ <child>
+ <object class="GtkImage" id="icon">
+ <property name="icon-name">security-high-symbolic</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Security</property>
+ <property name="hexpand">true</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage" id="next">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </property>
+
+ </template>
+</interface>
diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am
index f4a682c..be70445 100644
--- a/src/gui/Makefile.am
+++ b/src/gui/Makefile.am
@@ -12,15 +12,12 @@ libgui_la_SOURCES = \
item-int.h \
item.h item.c \
menubar.h menubar.c \
- panel-int.h \
- panel.h panel.c \
resources.h resources.c \
status.h status.c \
theme.h theme.c
libgui_la_LIBADD = \
core/libguicore.la \
- dialogs/libguidialogs.la \
menus/libguimenus.la \
panels/libguipanels.la \
tb/libguitb.la
@@ -28,10 +25,15 @@ libgui_la_LIBADD = \
libgui_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
-libgui4_la_SOURCES =
+libgui4_la_SOURCES = \
+ resources.h resources.c \
+ window-int.h \
+ window.h window.c
-libgui4_la_LIBADD = \
- core/libguicore4.la
+libgui4_la_LIBADD = \
+ core/libguicore4.la \
+ dialogs/libguidialogs.la \
+ panels/libguipanels4.la
libgui4_la_CFLAGS = $(LIBGTK4_CFLAGS)
@@ -41,10 +43,14 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libgui_la_SOURCES:%c=)
-SUBDIRS = core # dialogs menus panels tb
+SUBDIRS = core dialogs panels # menus panels tb
-resources.c: gresource.xml $(UI_FILES)
+RES_FILES = \
+ style.css \
+ window.ui
+
+resources.c: gresource.xml $(RES_FILES)
glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name gui gresource.xml
resources.h: gresource.xml
@@ -53,4 +59,4 @@ resources.h: gresource.xml
CLEANFILES = resources.h resources.c
-EXTRA_DIST = gresource.xml $(UI_FILES)
+EXTRA_DIST = gresource.xml $(RES_FILES)
diff --git a/src/gui/core/Makefile.am b/src/gui/core/Makefile.am
index 96ef578..a854977 100644
--- a/src/gui/core/Makefile.am
+++ b/src/gui/core/Makefile.am
@@ -15,7 +15,6 @@ RES_FILES = \
libguicore_la_SOURCES = \
global.h global.c \
items.h items.c \
- panels.h panels.c \
resources.h resources.c \
theme.h theme.c
@@ -24,7 +23,9 @@ libguicore_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
libguicore4_la_SOURCES = \
core.h core.c \
- logs.h logs.c
+ logs.h logs.c \
+ nox.h nox.c \
+ panels.h panels.c
libguicore4_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/gui/core/core.c b/src/gui/core/core.c
index 2d47dc9..57a398a 100644
--- a/src/gui/core/core.c
+++ b/src/gui/core/core.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* core.c - chargement et le déchargement du tronc commun pour l'éditeur graphique
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,6 +24,7 @@
#include "core.h"
+#include "panels.h"
#include "../../glibext/linetoken.h"
@@ -32,6 +33,7 @@
static AvailableGuiComponent __loaded = AGC_NONE;
+
/******************************************************************************
* *
* Paramètres : flags = liste d'éléments à charger. *
@@ -59,6 +61,15 @@ bool load_gui_components(AvailableGuiComponent flags)
}
+ if ((flags & AGC_PANELS) != 0 && (__loaded & AGC_PANELS) == 0)
+ {
+ result = load_main_framework_panel_definitions();
+ if (!result) goto done;
+
+ __loaded |= AGC_PANELS;
+
+ }
+
done:
return result;
@@ -80,6 +91,14 @@ bool load_gui_components(AvailableGuiComponent flags)
void unload_gui_components(AvailableGuiComponent flags)
{
+ if ((flags & AGC_PANELS) != 0 && (__loaded & AGC_PANELS) == 0)
+ {
+ unload_all_framework_panel_definitions();
+
+ __loaded &= ~AGC_PANELS;
+
+ }
+
if ((flags & AGC_BUFFER_FEATURES) != 0 && (__loaded & AGC_BUFFER_FEATURES) == 0)
{
exit_segment_content_hash_table();
@@ -87,7 +106,6 @@ void unload_gui_components(AvailableGuiComponent flags)
__loaded &= ~AGC_BUFFER_FEATURES;
}
-
}
diff --git a/src/gui/core/core.h b/src/gui/core/core.h
index bcb5433..19647ce 100644
--- a/src/gui/core/core.h
+++ b/src/gui/core/core.h
@@ -34,6 +34,7 @@ typedef enum _AvailableGuiComponent
{
AGC_NONE = (0 << 0), /* Statut initial */
AGC_BUFFER_FEATURES = (1 << 0), /* Tampons de bribes de texte */
+ AGC_PANELS = (1 << 1), /* Panneaux graphiques de base */
} AvailableGuiComponent;
diff --git a/src/gui/core/logs.c b/src/gui/core/logs.c
index 59910f1..cdb2a0d 100644
--- a/src/gui/core/logs.c
+++ b/src/gui/core/logs.c
@@ -24,6 +24,14 @@
#include "logs.h"
+#include <assert.h>
+
+
+#include "panels.h"
+#include "../panels/logs.h"
+#include "../../glibext/log.h"
+
+
/******************************************************************************
* *
@@ -38,26 +46,20 @@
* *
******************************************************************************/
-void do_log_message_alt2(LogMessageType type, const char *msg)
+void do_log_message_alt(LogMessageType type, const char *msg)
{
-#if 0
-
-#ifdef INCLUDE_GTK_SUPPORT
-
- GEditorItem *item; /* Eventuel affichage présent */
+ GLogEntry *entry; /* Nouvel élément de journal */
+ GtkTiledPanel *panel; /* Panneau de journalisation */
- item = find_editor_item_by_type(G_TYPE_LOG_PANEL);
+ entry = g_log_entry_new(type, msg);
- if (item != NULL)
- {
- g_log_panel_add_message(G_LOG_PANEL(item), type, msg);
- g_object_unref(G_OBJECT(item));
- }
+ panel = get_framework_panel_singleton(GTK_TYPE_LOGS_PANEL);
+ assert(panel != NULL);
-#endif
+ g_log_panel_add_message(GTK_LOGS_PANEL(panel), entry);
-#endif
+ unref_object(panel);
- printf("[log GUI] [%u] %s\n", type, msg);
+ unref_object(entry);
}
diff --git a/src/gui/core/nox.c b/src/gui/core/nox.c
new file mode 100644
index 0000000..7f3ae1f
--- /dev/null
+++ b/src/gui/core/nox.c
@@ -0,0 +1,48 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * nox.c - indication de présence ou d'absence de support graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "nox.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Indique la présence ou l'absence d'un affichage graphique. *
+* *
+* Retour : Statut à transmettre. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _run_in_nox_mode(void)
+{
+ bool result; /* Statut à retournr */
+
+ result = false;
+
+ return result;
+
+}
diff --git a/src/gui/core/nox.h b/src/gui/core/nox.h
new file mode 100644
index 0000000..e03b365
--- /dev/null
+++ b/src/gui/core/nox.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * nox.h - prototypes pour l'indication de présence ou d'absence de support graphique
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_CORE_NOX_H
+#define _GUI_CORE_NOX_H
+
+
+#include <stdbool.h>
+
+
+
+/* Indique la présence ou l'absence d'un affichage graphique. */
+bool _run_in_nox_mode(void);
+
+
+
+#endif /* _GUI_CORE_NOX_H */
diff --git a/src/gui/core/panels.c b/src/gui/core/panels.c
index 1b6f604..9fca411 100644
--- a/src/gui/core/panels.c
+++ b/src/gui/core/panels.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * panels.c - gestion d'ensemble de tous les panneaux pour l'éditeur
+ * panels.c - gestion d'ensemble de tous les panneaux graphiques du framework
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -27,35 +27,100 @@
#include <assert.h>
#include <malloc.h>
+#include <string.h>
-#include "items.h"
-#include "../panel-int.h"
-#include "../panels/bintree.h"
-#include "../panels/bookmarks.h"
-#include "../panels/errors.h"
-#include "../panels/glance.h"
-#include "../panels/history.h"
-#include "../panels/log.h"
-#include "../panels/regedit.h"
-#include "../panels/strings.h"
-#include "../panels/symbols.h"
+#include <i18n.h>
+
+
+#include "../panels/binary.h"
+#include "../panels/binary-params.h"
+#include "../panels/logs.h"
#include "../panels/welcome.h"
-#include "../../core/params.h"
+#include "../../gtkext/launcher.h"
+
+
+
+/* Définition générique complète d'un panneau */
+typedef struct _ext_panel_info_t
+{
+ /* Début des champs copiés de panel_info_t */
+
+ char *category; /* Groupe de rassemblement */
+
+ char *image; /* Eventuelle image associée */
+ char *title; /* Désignation humaine */
+ char *desc; /* Description humaine */
+
+ FrameworkPanelPersonality personality; /* Comportement attendu */
+
+ GType panel_type; /* Type du panneau représenté */
+ GType params_type; /* Composant de paramètre */
+
+ /* Fin des champs copiés de panel_info_t */
+
+ GtkTiledPanel *singleton; /* Conservation des allocations*/
+} ext_panel_info_t;
/* Liste des panneaux disponibles */
-static GType *_panels_list = NULL;
+static ext_panel_info_t **_panels_list = NULL;
static size_t _panels_count = 0;
+/* Copie une définition basique de panneau graphqiue. */
+static ext_panel_info_t *copy_panel_info(const panel_info_t *);
+
+/* Efface une définition étendue de panneau graphique. */
+static void delete_panel_info(ext_panel_info_t *);
+
+
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : info = information de base à copier. *
+* *
+* Description : Copie une définition basique de panneau graphqiue. *
+* *
+* Retour : Structure mémorisant l'ensemble des informations. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ext_panel_info_t *copy_panel_info(const panel_info_t *info)
+{
+ ext_panel_info_t *result; /* Structure à retourner */
+
+ result = calloc(1, sizeof(ext_panel_info_t));
+
+ if (info->category != NULL)
+ result->category = strdup(info->category);
+
+ if (info->image != NULL)
+ result->image = strdup(info->image);
+
+ result->title = strdup(info->title);
+
+ if (info->desc != NULL)
+ result->desc = strdup(info->desc);
+
+ result->personality = info->personality;
+
+ result->panel_type = info->panel_type;
+ result->params_type = info->params_type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
* *
-* Description : Charge les principaux panneaux de l'éditeur. *
+* Paramètres : info = informations à supprimer de la mémoire. *
+* *
+* Description : Efface une définition étendue de panneau graphique. *
* *
* Retour : - *
* *
@@ -63,38 +128,132 @@ static size_t _panels_count = 0;
* *
******************************************************************************/
-void load_main_panels(void)
+static void delete_panel_info(ext_panel_info_t *info)
{
- GGenConfig *config; /* Configuration globale */
- GPanelItem *panel; /* Panneau à précharger */
+ if (info->category != NULL)
+ free(info->category);
+
+ if (info->image != NULL)
+ free(info->image);
+
+ free(info->title);
+
+ if (info->desc != NULL)
+ free(info->desc);
+
+ if (info->singleton != NULL)
+ {
+ assert(info->personality & FPP_SINGLETON);
+ unref_object(info->singleton);
+ }
+
+ free(info);
+
+}
- config = get_main_configuration();
- register_panel_item(G_TYPE_LOG_PANEL, config);
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Charge les définitions des principaux panneaux du framework. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_main_framework_panel_definitions(void)
+{
+ bool result; /* Bilan à retourner */
+ panel_info_t info; /* Infos d'enregistrement */
/* Chargement du panneau de rapport au plus tôt */
- panel = g_panel_item_new(G_TYPE_LOG_PANEL, NULL);
- g_object_unref(G_OBJECT(panel));
-
- register_panel_item(G_TYPE_WELCOME_PANEL, config);
- register_panel_item(G_TYPE_REGEDIT_PANEL, config);
- register_panel_item(G_TYPE_SYMBOLS_PANEL, config);
- register_panel_item(G_TYPE_HISTORY_PANEL, config);
- register_panel_item(G_TYPE_STRINGS_PANEL, config);
- register_panel_item(G_TYPE_GLANCE_PANEL, config);
- register_panel_item(G_TYPE_BOOKMARKS_PANEL, config);
- register_panel_item(G_TYPE_BINTREE_PANEL, config);
- register_panel_item(G_TYPE_ERROR_PANEL, config);
+
+ info.category = NULL;
+
+ info.image = NULL;
+ info.title = _("Logs");
+ info.desc = NULL;
+
+ info.personality = FPP_SINGLETON;
+
+ info.panel_type = GTK_TYPE_LOGS_PANEL;
+ info.params_type = G_TYPE_INVALID;
+
+ result = register_framework_panel_definition(&info);
+ if (!result) goto done;
+
+ /* Chargements des panneaux restants */
+
+ info.category = "Main";
+
+ info.image = "binfile-symbolic";
+ info.title = _("Binary analysis");
+ info.desc = _("Load a binary content and parse its format if recognized");
+
+ info.personality = FPP_MAIN_PANEL;
+
+ info.panel_type = GTK_TYPE_BINARY_PANEL;
+ info.params_type = GTK_TYPE_BINARY_PARAMETERS;
+
+ result = register_framework_panel_definition(&info);
+ if (!result) goto done;
+
+ /* --- */
+
+ info.category = NULL;
+
+ info.image = NULL;
+ info.title = _("Welcome");
+ info.desc = NULL;
+
+ info.personality = FPP_MAIN_PANEL | FPP_SINGLETON;
+
+ info.panel_type = GTK_TYPE_WELCOME_PANEL;
+ info.params_type = G_TYPE_INVALID;
+
+ result = register_framework_panel_definition(&info);
+ if (!result) goto done;
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Décharge tous les panneaux graphiques du framework. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unload_all_framework_panel_definitions(void)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < _panels_count; i++)
+ delete_panel_info(_panels_list[i]);
+
+ _panels_list = NULL;
+ _panels_count = 0;
}
/******************************************************************************
* *
-* Paramètres : type = type du composant à présenter à l'affichage. *
-* config = configuration à compléter. *
+* Paramètres : info = information de base à copier. *
* *
-* Description : Enregistre un panneau comme partie intégrante de l'éditeur. *
+* Description : Enregistre la définition d'un panneau graphique. *
* *
* Retour : - *
* *
@@ -102,71 +261,199 @@ void load_main_panels(void)
* *
******************************************************************************/
-void register_panel_item(GType type, GGenConfig *config)
+bool register_framework_panel_definition(const panel_info_t *info)
{
- GPanelItemClass *class; /* Classe associée au type */
-#ifndef NDEBUG
- bool status; /* Bilan de mise en place */
-#endif
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ ext_panel_info_t *ext_info; /* Informations conservées */
+
+ result = false;
+
+ /* Validation */
+
+ for (i = 0; i < _panels_count; i++)
+ if (_panels_list[i]->panel_type == info->panel_type)
+ break;
- _panels_list = realloc(_panels_list, ++_panels_count * sizeof(GType));
+ if (i < _panels_count)
+ goto done;
- _panels_list[_panels_count - 1] = type;
+ /* Enregistrement */
- class = g_type_class_ref(type);
+ ext_info = copy_panel_info(info);
-#ifndef NDEBUG
- status = gtk_panel_item_class_setup_configuration(class, config);
- assert(status);
-#else
- gtk_panel_item_class_setup_configuration(class, config);
-#endif
+ _panels_list = realloc(_panels_list, ++_panels_count * sizeof(ext_panel_info_t *));
- g_type_class_unref(class);
+ _panels_list[_panels_count - 1] = ext_info;
+
+ result = true;
+
+ done:
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : skip = saute le panneau d'accueil lors du parcours ? *
-* handle = routine à appeler pour chaque panneau. *
-* data = données fournies pour accompagner cet appel. *
+* Paramètres : target = type de définition de panneau recherchée. *
* *
-* Description : Effectue le parcours de tous les panneaux chargés. *
+* Description : Récupère les particularités d'un panneau graphique. *
* *
-* Retour : true si le parcours a été total, false sinon. *
+* Retour : Détails du comportement associé au panneau visé. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _browse_all_item_panels(bool skip, handle_panel_item_fc handle, void *data)
+FrameworkPanelPersonality get_framework_panel_personality(GType target)
{
- bool result; /* Résultat à renvoyer */
- GType type; /* Type de panneau à traiter */
+ FrameworkPanelPersonality result; /* Propriétées à retourner */
size_t i; /* Boucle de parcours */
- GPanelItemClass *class; /* Classe associée au type */
+ ext_panel_info_t *info; /* Informations conservées */
- result = true;
+ result = FPP_NONE;
+
+ for (i = 0; i < _panels_count; i++)
+ {
+ info = _panels_list[i];
+
+ if (info->panel_type == target)
+ {
+ result = info->personality;
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = type de définition de panneau recherchée. *
+* *
+* Description : Met en place (au besoin) un panneau graphique unique. *
+* *
+* Retour : Instance de définition identifiée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkTiledPanel *get_framework_panel_singleton(GType target)
+{
+ GtkTiledPanel *result; /* Instance à renvoyer */
+ size_t i; /* Boucle de parcours */
+ ext_panel_info_t *info; /* Informations conservées */
+
+ result = NULL;
+
+ for (i = 0; i < _panels_count; i++)
+ {
+ info = _panels_list[i];
+
+ if (info->panel_type == target)
+ {
+ if (info->singleton == NULL)
+ info->singleton = g_object_new(target, NULL);
+
+ result = info->singleton;
+ ref_object(result);
+ break;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste à compléter. *
+* *
+* Description : Intègre une définition de panneau enregistrée. *
+* *
+* Retour : true pour un parcours complet de la liste des définitions. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void populate_framework_panel_launcher_list(GtkListBox *list)
+{
+ size_t i; /* Boucle de parcours */
+ ext_panel_info_t *info; /* Informations conservées */
+ GtkPanelLauncher *launcher; /* Lanceur à intégrer */
for (i = 0; i < _panels_count; i++)
{
- type = _panels_list[i];
+ info = _panels_list[i];
- if (skip && type == G_TYPE_WELCOME_PANEL)
+ if (info->category == NULL)
continue;
- class = g_type_class_ref(type);
+ launcher = gtk_panel_launcher_new(info->image, info->title, info->desc);
+
+ g_object_set_data(G_OBJECT(launcher), "panel_type", GSIZE_TO_POINTER(info->panel_type));
+
+ gtk_list_box_append(list, GTK_WIDGET(launcher));
- result = handle(class, data);
+ }
+
+}
- g_type_class_unref(class);
- if (!result) break;
+/******************************************************************************
+* *
+* Paramètres : row = lanceur sélectionné. *
+* *
+* Description : Fournit un composant d'édition de paramètres de panneau. *
+* *
+* Retour : Composant d'édition de paramètres ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *get_framework_panel_parameters(GtkListBoxRow *row)
+{
+ GtkWidget *result; /* Composant à retourner */
+ gpointer *data; /* Valeur incrustée */
+ GType target; /* Type de panneau recherché */
+ ext_panel_info_t *info; /* Informations conservées */
+ size_t i; /* Boucle de parcours */
+
+ data = g_object_get_data(G_OBJECT(row), "panel_type");
+ assert(data != NULL);
+
+ target = GPOINTER_TO_SIZE(data);
+
+ info = NULL;
+
+ for (i = 0; i < _panels_count; i++)
+ {
+ info = _panels_list[i];
+
+ if (info->panel_type == target)
+ break;
}
+ assert(info != NULL);
+ assert(i < _panels_count);
+
+ if (info->params_type == G_TYPE_INVALID)
+ result = NULL;
+ else
+ result = g_object_new(info->params_type, NULL);
+
return result;
}
diff --git a/src/gui/core/panels.h b/src/gui/core/panels.h
index 3846038..e17ef8a 100644
--- a/src/gui/core/panels.h
+++ b/src/gui/core/panels.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * panels.h - prototypes pour la gestion d'ensemble de tous les panneaux pour l'éditeur
+ * panels.h - prototypes pour la gestion d'ensemble de tous les panneaux graphiques du framework
*
- * Copyright (C) 2016-2019 Cyrille Bagard
+ * Copyright (C) 2016-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,28 +26,62 @@
#define _GUI_CORE_PANELS_H
+#include <glib-object.h>
#include <stdbool.h>
+#include <gtk/gtk.h>
-#include "../panel.h"
-#include "../../glibext/configuration.h"
+#include "../../gtkext/panel.h"
-/* Charge les principaux panneaux de l'éditeur. */
-void load_main_panels(void);
+/* Types de panneaux pour éditeur */
+typedef enum _FrameworkPanelPersonality
+{
+ FPP_NONE = (0 << 0), /* Pas de particularité */
-/* Enregistre un panneau comme partie intégrante de l'éditeur. */
-void register_panel_item(GType, GGenConfig *);
+ FPP_MAIN_PANEL = (1 << 0), /* Panneau principal */
+ FPP_SINGLETON = (1 << 1), /* Instance unique */
-/* Réalise un traitement sur un panneau de l'éditeur. */
-typedef bool (* handle_panel_item_fc) (GPanelItemClass *, void *);
+} FrameworkPanelPersonality;
-/* Effectue le parcours de tous les panneaux chargés. */
-bool _browse_all_item_panels(bool, handle_panel_item_fc, void *);
+/* Définition générique d'un panneau */
+typedef struct _panel_info_t
+{
+ const char *category; /* Groupe de rassemblement */
-#define browse_all_item_panels(h, d) \
- _browse_all_item_panels(false, h, d)
+ const char *image; /* Eventuelle image associée */
+ const char *title; /* Désignation humaine */
+ const char *desc; /* Description humaine */
+
+ FrameworkPanelPersonality personality; /* Comportement attendu */
+
+ GType panel_type; /* Type du panneau représenté */
+ GType params_type; /* Composant de paramètre */
+
+} panel_info_t;
+
+
+/* Charge les définitions des principaux panneaux du framework. */
+bool load_main_framework_panel_definitions(void);
+
+/* Décharge tous les panneaux graphiques du framework. */
+void unload_all_framework_panel_definitions(void);
+
+/* Enregistre la définition d'un panneau graphique. */
+bool register_framework_panel_definition(const panel_info_t *);
+
+/* Récupère les particularités d'un panneau graphique. */
+FrameworkPanelPersonality get_framework_panel_personality(GType);
+
+/* Met en place (au besoin) un panneau graphique unique. */
+GtkTiledPanel *get_framework_panel_singleton(GType);
+
+/* Intègre une définition de panneau enregistrée. */
+void populate_framework_panel_launcher_list(GtkListBox *);
+
+/* Fournit un composant d'édition de paramètres de panneau. */
+GtkWidget *get_framework_panel_parameters(GtkListBoxRow *);
diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am
index 5716f14..3492f63 100644
--- a/src/gui/dialogs/Makefile.am
+++ b/src/gui/dialogs/Makefile.am
@@ -3,35 +3,43 @@ BUILT_SOURCES = resources.h resources.c
noinst_LTLIBRARIES = libguidialogs.la
-UI_FILES = \
- about.ui \
- bookmark.ui \
- export_graph.ui \
- identity.ui \
- loading.ui \
- preferences.ui \
- prefs_fgraph.ui \
- prefs_labels.ui \
- snapshots.ui \
- storage.ui
-
-libguidialogs_la_SOURCES = \
- about.h about.c \
- bookmark.h bookmark.c \
- export_disass.h export_disass.c \
- export_graph.h export_graph.c \
- goto.h goto.c \
- gotox.h gotox.c \
- identity.h identity.c \
- loading.h loading.c \
- preferences.h preferences.c \
- prefs_fgraph.h prefs_fgraph.c \
- prefs_labels.h prefs_labels.c \
- resources.h resources.c \
- snapshots.h snapshots.c \
- storage.h storage.c
-
-libguidialogs_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+
+UI_FILES = \
+ about.css \
+ about.ui \
+ preferences.ui
+# bookmark.ui \
+# export_graph.ui \
+# identity.ui \
+# loading.ui \
+# prefs_fgraph.ui \
+# prefs_labels.ui \
+# snapshots.ui \
+# storage.ui
+
+libguidialogs_la_SOURCES = \
+ about-int.h \
+ about.h about.c \
+ preferences-int.h \
+ preferences.h preferences.c \
+ resources.h resources.c
+# bookmark.h bookmark.c \
+# export_disass.h export_disass.c \
+# export_graph.h export_graph.c \
+# goto.h goto.c \
+# gotox.h gotox.c \
+# identity.h identity.c \
+# loading.h loading.c \
+# \
+# prefs_fgraph.h prefs_fgraph.c \
+# prefs_labels.h prefs_labels.c \
+# snapshots.h snapshots.c \
+# storage.h storage.c
+
+libguidialogs_la_LIBADD = \
+ prefs/libguidialogsprefs.la
+
+libguidialogs_la_CFLAGS = $(LIBGTK4_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
@@ -39,6 +47,9 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libguidialogs_la_SOURCES:%c=)
+SUBDIRS = prefs
+
+
resources.c: gresource.xml $(UI_FILES)
glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name gui_dialogs gresource.xml
diff --git a/src/gui/dialogs/about-int.h b/src/gui/dialogs/about-int.h
new file mode 100644
index 0000000..96a470e
--- /dev/null
+++ b/src/gui/dialogs/about-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * about-int.h - définitions internes pour la boîte de dialogue d'information sur le programme
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_ABOUT_INT_H
+#define _GUI_DIALOGS_ABOUT_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "about.h"
+
+
+
+/* Boîte "A propos de" dédiée à l'application (instance) */
+struct _GtkAppAboutDialog
+{
+ GtkWindow parent; /* A laisser en premier */
+
+};
+
+/* Boîte "A propos de" dédiée à l'application (classe) */
+struct _GtkAppAboutDialogClass
+{
+ GtkWindowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place la fenêtre d'informations sur le logiciel. */
+bool gtk_app_about_dialog_create(GtkAppAboutDialog *, GtkWindow *);
+
+
+
+#endif /* _GUI_DIALOGS_ABOUT_INT_H */
diff --git a/src/gui/dialogs/about.c b/src/gui/dialogs/about.c
index 574c7f2..1dca752 100644
--- a/src/gui/dialogs/about.c
+++ b/src/gui/dialogs/about.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* about.h - boîte de dialogue d'information sur le programme
*
- * Copyright (C) 2015-2020 Cyrille Bagard
+ * Copyright (C) 2015-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -33,143 +33,168 @@
#include <config.h>
-#include "../../gtkext/easygtk.h"
+#include "about-int.h"
-/* Réagit à l'appui d'une touche sur la fenêtre 'A propos'. */
-static gboolean close_about_window_on_escape(GtkWidget *, GdkEventKey *, gpointer);
+/* Procède à l'initialisation de la boîte "A propos de". */
+static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *);
-/* Dessine un fond adapté pour la fenêtre sans toucher au thème. */
-static gboolean draw_black_background(GtkWidget *, cairo_t *, gpointer);
+/* Procède à l'initialisation de la boîte "A propos de". */
+static void gtk_app_about_dialog_init(GtkAppAboutDialog *);
+/* Supprime toutes les références externes. */
+static void gtk_app_about_dialog_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_app_about_dialog_finalize(GObject *);
+
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkAppAboutDialog, gtk_app_about_dialog, GTK_TYPE_WINDOW);
/******************************************************************************
* *
-* Paramètres : parent = fenêtre parente à surpasser. *
-* outb = constructeur à détruire après usage. [OUT] *
+* Paramètres : class = classe GTK à initialiser. *
* *
-* Description : Construit la fenêtre d'informations sur le logiciel. *
+* Description : Procède à l'initialisation de la boîte "A propos de". *
* *
-* Retour : Adresse de la fenêtre mise en place. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GtkWidget *create_about_dialog(GtkWindow *parent, GtkBuilder **outb)
+static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *class)
{
- GtkWidget *result; /* Fenêtre à renvoyer */
- GtkBuilder *builder; /* Constructeur utilisé */
- unsigned int revision; /* Numéro de révision */
- unsigned int max; /* Nbre. de boucles à effectuer*/
- unsigned int i; /* Boucle de parcours */
- unsigned int level; /* Unité la plus importante */
- char buffer[64]; /* Nom d'image à forger */
- GtkImage *img; /* Composant d'affichage */
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
- builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/about.ui");
- *outb = builder;
+ object = G_OBJECT_CLASS(class);
- result = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ object->dispose = gtk_app_about_dialog_dispose;
+ object->finalize = gtk_app_about_dialog_finalize;
- gtk_window_set_transient_for(GTK_WINDOW(result), parent);
+ widget = GTK_WIDGET_CLASS(class);
- /* Numéro de révision */
+ gtk_widget_class_set_css_name(widget, "aboutdialog");
- revision = REVISION;
- max = log(revision) / log(10);
+ gtk_widget_class_add_binding_action(widget, GDK_KEY_Escape, 0, "window.close", NULL);
- assert(max <= 6);
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/about.ui");
- for (i = 0; i <= max; i++)
- {
- snprintf(buffer, 64, "revision_%u", i);
+}
- img = GTK_IMAGE(gtk_builder_get_object(builder, buffer));
- level = pow(10, max - i);
+/******************************************************************************
+* *
+* Paramètres : dialog = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de la boîte "A propos de". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- snprintf(buffer, 64, "/org/chrysalide/gui/dialogs/about/revision_%u.png", revision / level);
+static void gtk_app_about_dialog_init(GtkAppAboutDialog *dialog)
+{
+ gtk_widget_init_template(GTK_WIDGET(dialog));
- gtk_image_set_from_resource(img, buffer);
+}
- revision %= level;
- }
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- /* Connexion des signaux */
+static void gtk_app_about_dialog_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_APP_ABOUT_DIALOG);
- gtk_builder_add_callback_symbols(builder,
- BUILDER_CALLBACK(close_about_window_on_escape),
- BUILDER_CALLBACK(draw_black_background),
- NULL);
+ G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->dispose(object);
- gtk_builder_connect_signals(builder, builder);
+}
- return result;
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_app_about_dialog_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->finalize(object);
}
/******************************************************************************
* *
-* Paramètres : widget = fenêtre visée par la procédure. *
-* event = informations liées à l'événement. *
-* dummy = donnée non utilisée ici. *
+* Paramètres : parent = fenêtre parente à surpasser. *
* *
-* Description : Réagit à l'appui d'une touche sur la fenêtre 'A propos'. *
+* Description : Construit la fenêtre d'informations sur le logiciel. *
* *
-* Retour : TRUE pour interrompre la propagation, FALSE autrement. *
+* Retour : Adresse de la fenêtre mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-static gboolean close_about_window_on_escape(GtkWidget *widget, GdkEventKey *event, gpointer dummy)
+GtkWindow *gtk_app_about_dialog_new(GtkWindow *parent)
{
- gboolean result; /* Ordre à retourner */
+ GtkWindow *result; /* Boite de dialogue à renvoyer*/
+
+ result = g_object_new(GTK_TYPE_APP_ABOUT_DIALOG, NULL);
- if (event->keyval == GDK_KEY_Escape)
- {
- gtk_widget_destroy(widget);
- result = TRUE;
- }
- else result = FALSE;
+ if (!gtk_app_about_dialog_create(GTK_APP_ABOUT_DIALOG(result), parent))
+ g_clear_object(&result);
return result;
}
+
/******************************************************************************
* *
-* Paramètres : widget = fenêtre visée par la procédure. *
-* event = informations liées à l'événement. *
-* dummy = donnée non utilisée ici. *
+* Paramètres : dialog = boîte de dialogue à initialiser pleinement. *
+* parent = fenêtre parente à surpasser. *
* *
-* Description : Dessine un fond adapté pour la fenêtre sans toucher au thème.*
+* Description : Met en place la fenêtre d'informations sur le logiciel. *
* *
-* Retour : TRUE pour interrompre la propagation, FALSE autrement. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static gboolean draw_black_background(GtkWidget *widget, cairo_t *cr, gpointer dummy)
+bool gtk_app_about_dialog_create(GtkAppAboutDialog *dialog, GtkWindow *parent)
{
- int width; /* Largeur du composant */
- int height; /* Hauteur du composant */
+ bool result; /* Bilan à retourner */
- width = gtk_widget_get_allocated_width(widget);
- height = gtk_widget_get_allocated_height(widget);
+ result = true;
- cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
- cairo_rectangle(cr, 0, 0, width, height);
- cairo_fill(cr);
-
- return FALSE;
+ return result;
}
diff --git a/src/gui/dialogs/about.css b/src/gui/dialogs/about.css
new file mode 100644
index 0000000..af3fa97
--- /dev/null
+++ b/src/gui/dialogs/about.css
@@ -0,0 +1,9 @@
+
+aboutdialog > box {
+
+ background-color: black;
+
+ background-image: url('resource:///re/chrysalide/framework/gui/dialogs/about/bg.png');
+ background-repeat: no-repeat;
+
+}
diff --git a/src/gui/dialogs/about.h b/src/gui/dialogs/about.h
index f119f67..e569ad3 100644
--- a/src/gui/dialogs/about.h
+++ b/src/gui/dialogs/about.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* about.h - prototypes pour la boîte de dialogue d'information sur le programme
*
- * Copyright (C) 2015-2020 Cyrille Bagard
+ * Copyright (C) 2015-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,9 +28,17 @@
#include <gtk/gtk.h>
+#include "../../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_APP_ABOUT_DIALOG (gtk_app_about_dialog_get_type())
+
+DECLARE_GTYPE(GtkAppAboutDialog, gtk_app_about_dialog, GTK, APP_ABOUT_DIALOG);
+
/* Construit la fenêtre d'informations sur le logiciel. */
-GtkWidget *create_about_dialog(GtkWindow *, GtkBuilder **);
+GtkWindow *gtk_app_about_dialog_new(GtkWindow *);
diff --git a/src/gui/dialogs/about.ui b/src/gui/dialogs/about.ui
index 0170508..7b519d2 100644
--- a/src/gui/dialogs/about.ui
+++ b/src/gui/dialogs/about.ui
@@ -1,151 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.37.0 -->
<interface>
- <requires lib="gtk+" version="3.12"/>
- <object class="GtkWindow" id="window">
- <property name="width-request">350</property>
- <property name="height-request">430</property>
- <property name="can-focus">False</property>
- <property name="border-width">0</property>
- <property name="title" translatable="yes">About</property>
- <property name="resizable">False</property>
- <property name="modal">True</property>
- <property name="window-position">center-on-parent</property>
- <property name="default-width">350</property>
- <property name="default-height">430</property>
- <property name="type-hint">dialog</property>
- <signal name="key-press-event" handler="close_about_window_on_escape" swapped="no"/>
- <child>
- <object class="GtkFixed">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <signal name="draw" handler="draw_black_background" swapped="no"/>
- <child>
- <object class="GtkLabel">
- <property name="width-request">350</property>
- <property name="height-request">20</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="margin-bottom">10</property>
- <property name="label" translatable="yes">&lt;span fgcolor='white'&gt;Copyright (C) 2008-2020 Cyrille Bagard&lt;/span&gt;</property>
- <property name="use-markup">True</property>
- </object>
- <packing>
- <property name="y">400</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="logo">
- <property name="width-request">330</property>
- <property name="height-request">300</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="resource">/org/chrysalide/gui/dialogs/about/chrysalide-full.png</property>
- </object>
- <packing>
- <property name="x">10</property>
- <property name="y">10</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="text">
- <property name="width-request">253</property>
- <property name="height-request">42</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="resource">/org/chrysalide/gui/dialogs/about/chrysalide_text.png</property>
- </object>
- <packing>
- <property name="x">48</property>
- <property name="y">324</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="resource">/org/chrysalide/gui/dialogs/about/revision.png</property>
- </object>
- <packing>
- <property name="x">149</property>
- <property name="y">360</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision_0">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- </object>
- <packing>
- <property name="x">163</property>
- <property name="y">360</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision_1">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- </object>
- <packing>
- <property name="x">177</property>
- <property name="y">360</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision_2">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- </object>
- <packing>
- <property name="x">191</property>
- <property name="y">360</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision_3">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- </object>
- <packing>
- <property name="x">205</property>
- <property name="y">360</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision_4">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- </object>
- <packing>
- <property name="x">219</property>
- <property name="y">360</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="revision_5">
- <property name="width-request">14</property>
- <property name="height-request">18</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- </object>
- <packing>
- <property name="x">233</property>
- <property name="y">360</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
+
+ <template class="GtkAppAboutDialog" parent="GtkWindow">
+ <property name="title" translatable="yes">About</property>
+ <property name="default-width">350</property>
+ <property name="default-height">430</property>
+ <property name="modal">true</property>
+ <property name="resizable">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="margin-top">368</property>
+ <property name="margin-bottom">10</property>
+ <property name="label" translatable="yes">&lt;span fgcolor='white'&gt;Copyright (C) 2008-2025 Cyrille Bagard&lt;/span&gt;</property>
+ <property name="use-markup">True</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
</interface>
diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml
index 0e12ef2..966d9c8 100644
--- a/src/gui/dialogs/gresource.xml
+++ b/src/gui/dialogs/gresource.xml
@@ -1,30 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
- <gresource prefix="/org/chrysalide/gui/dialogs">
+ <gresource prefix="/re/chrysalide/framework/gui/dialogs">
+ <file compressed="true">about.css</file>
<file compressed="true">about.ui</file>
- <file compressed="true">bookmark.ui</file>
- <file compressed="true">export_graph.ui</file>
- <file compressed="true">identity.ui</file>
- <file compressed="true">loading.ui</file>
<file compressed="true">preferences.ui</file>
- <file compressed="true">prefs_fgraph.ui</file>
- <file compressed="true">prefs_labels.ui</file>
- <file compressed="true">snapshots.ui</file>
- <file compressed="true">storage.ui</file>
- </gresource>
- <gresource prefix="/org/chrysalide/gui/dialogs/about">
- <file compressed="true" alias="chrysalide-full.png">../../../pixmaps/chrysalide-full.png</file>
- <file compressed="true" alias="chrysalide_text.png">../../../pixmaps/chrysalide_text.png</file>
- <file compressed="true" alias="revision.png">../../../pixmaps/revision.png</file>
- <file compressed="true" alias="revision_0.png">../../../pixmaps/revision_0.png</file>
- <file compressed="true" alias="revision_1.png">../../../pixmaps/revision_1.png</file>
- <file compressed="true" alias="revision_2.png">../../../pixmaps/revision_2.png</file>
- <file compressed="true" alias="revision_3.png">../../../pixmaps/revision_3.png</file>
- <file compressed="true" alias="revision_4.png">../../../pixmaps/revision_4.png</file>
- <file compressed="true" alias="revision_5.png">../../../pixmaps/revision_5.png</file>
- <file compressed="true" alias="revision_6.png">../../../pixmaps/revision_6.png</file>
- <file compressed="true" alias="revision_7.png">../../../pixmaps/revision_7.png</file>
- <file compressed="true" alias="revision_8.png">../../../pixmaps/revision_8.png</file>
- <file compressed="true" alias="revision_9.png">../../../pixmaps/revision_9.png</file>
</gresource>
</gresources>
diff --git a/src/gui/dialogs/preferences-int.h b/src/gui/dialogs/preferences-int.h
new file mode 100644
index 0000000..806f5f6
--- /dev/null
+++ b/src/gui/dialogs/preferences-int.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * preferences-int.h - définitions internes pour la boîte de dialogue d'édition des préférences de l'utilisateur
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFERENCES_INT_H
+#define _GUI_DIALOGS_PREFERENCES_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "preferences.h"
+
+
+
+/* Fenêtre d'édition générale de la configuration (instance) */
+struct _GtkPreferencesDialog
+{
+ GtkWindow parent; /* A laisser en premier */
+
+ GtkLabel *side_title; /* Titre principal */
+ GtkScrolledWindow *side_content; /* Liste des sections */
+ GtkLabel *main_title; /* Titre de section */
+ GtkScrolledWindow *main_content; /* Page de configuration */
+
+ GHashTable *navigations; /* Liste de sections en place */
+
+};
+
+/* Fenêtre d'édition générale de la configuration (classe) */
+struct _GtkPreferencesDialogClass
+{
+ GtkWindowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place la boîte de dialogue pour les préférences. */
+bool gtk_preferences_dialog_create(GtkPreferencesDialog *, GtkWindow *);
+
+
+
+#endif /* _GUI_DIALOGS_PREFERENCES_INT_H */
diff --git a/src/gui/dialogs/preferences.c b/src/gui/dialogs/preferences.c
index 4a3fb7c..0369241 100644
--- a/src/gui/dialogs/preferences.c
+++ b/src/gui/dialogs/preferences.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * preferences.c - (re)définition de l'identité de l'utilisateur
+ * preferences.c - boîte de dialogue d'édition des préférences de l'utilisateur
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -24,129 +24,105 @@
#include "preferences.h"
-#include <i18n.h>
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <gdk/gdkkeysyms.h>
-#include "prefs_fgraph.h"
-#include "prefs_labels.h"
-#include "../../core/params.h"
-#include "../../gtkext/easygtk.h"
+#include <config.h>
+#include "preferences-int.h"
+#include "prefs/appearance.h"
+#include "prefs/security.h"
+#include "../../common/cpp.h"
+#include "../../gtkext/tweak.h"
+#include "../../plugins/pglist.h"
+#include "../../plugins/tweakable.h"
-/* Constructeur de panneau de paramétrage */
-typedef GtkWidget * (* prefs_panel_creation_cb) (GtkBuilder **);
-/* Chargement de la configuration */
-typedef void (* prefs_config_update_cb) (GtkBuilder *, GGenConfig *);
-/* Description d'un noeud de préférences */
-typedef struct _pref_node_desc_t
-{
- prefs_panel_creation_cb create; /* Procédure de création */
- prefs_config_update_cb load; /* Procédure de chargement */
- prefs_config_update_cb store; /* Procédure d'enregistrement */
-
- const char *name; /* Désignation interne */
- const char *title; /* Désignation humaine */
-
- GtkBuilder *builder; /* Constructeur GTK */
- GtkWidget *panel; /* Panneau GTK */
-
- struct _pref_node_desc_t *children; /* Sous-arborescence */
-
-} pref_node_desc_t;
-
-
-#define PREF_NODE_NULL_ENTRY { .title = NULL }
+/* --------------------------- BASES DE BOITE DE DIALOGUE --------------------------- */
-/* Liste des paramétrages à afficher */
-static pref_node_desc_t _prefs_nodes[] = {
+/* Procède à l'initialisation de la fenêtre des paramètres. */
+static void gtk_preferences_dialog_class_init(GtkPreferencesDialogClass *);
- {
- .create = NULL,
-
- .title = "Analysis",
+/* Procède à l'initialisation de la fenêtre des paramètres. */
+static void gtk_preferences_dialog_init(GtkPreferencesDialog *);
- .children = (pref_node_desc_t []){
+/* Supprime toutes les références externes. */
+static void gtk_preferences_dialog_dispose(GObject *);
- {
- .create = create_labels_preferences,
- .load = load_labels_configuration,
- .store = store_labels_configuration,
+/* Procède à la libération totale de la mémoire. */
+static void gtk_preferences_dialog_finalize(GObject *);
- .name = "labels",
- .title = "Colored labels",
+/* Fournit la liste de section désignée par un nom. */
+static GtkListBox *gtk_preferences_dialog_get_navigation(GtkPreferencesDialog *, const char *, bool);
- },
+/* Réagit à un changement de sélection dans les sections. */
+static void gtk_preferences_dialog_on_row_selected(GtkListBox *, GtkListBoxRow *, GtkPreferencesDialog *);
- PREF_NODE_NULL_ENTRY
- }
- },
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
- {
- .create = NULL,
- .title = "Editor",
- .children = (pref_node_desc_t []){
- {
- .create = create_fgraph_preferences,
- .load = load_fgraph_configuration,
- .store = store_fgraph_configuration,
- .name = "fgraph",
- .title = "Function graph",
+/* ---------------------------------------------------------------------------------- */
+/* BASES DE BOITE DE DIALOGUE */
+/* ---------------------------------------------------------------------------------- */
- },
-
- PREF_NODE_NULL_ENTRY
-
- }
- },
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkPreferencesDialog, gtk_preferences_dialog, GTK_TYPE_WINDOW);
- PREF_NODE_NULL_ENTRY
-
-};
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de la fenêtre des paramètres. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-/* Eléments de la liste de sections */
-typedef enum _PrefListItem
+static void gtk_preferences_dialog_class_init(GtkPreferencesDialogClass *class)
{
- PLI_TITLE, /* Etiquette de la section */
- PLI_PANEL, /* Panneau graphique associé */
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
-} PrefListItem;
+ object = G_OBJECT_CLASS(class);
+ object->dispose = gtk_preferences_dialog_dispose;
+ object->finalize = gtk_preferences_dialog_finalize;
-/* Ajoute un panneau de paramétrage à la boîte de dialogue. */
-static void add_preferences_node(GtkTreeStore *, GtkTreeIter *, GGenConfig *, GtkStack *, pref_node_desc_t *);
+ widget = GTK_WIDGET_CLASS(class);
-/* Affiche le panneau correspondant au noeud sélectionné. */
-static void on_prefs_selection_changed(GtkTreeSelection *, GtkBuilder *);
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/preferences.ui");
-/* Lance la sauvegarde d'éléments de paramétrage. */
-static void store_preferences_node(GGenConfig *, pref_node_desc_t *);
+ gtk_widget_class_bind_template_child(widget, GtkPreferencesDialog, side_title);
+ gtk_widget_class_bind_template_child(widget, GtkPreferencesDialog, side_content);
+ gtk_widget_class_bind_template_child(widget, GtkPreferencesDialog, main_title);
+ gtk_widget_class_bind_template_child(widget, GtkPreferencesDialog, main_content);
-/* Sauvegarde l'ensemble des paramètres de configuration. */
-static void on_prefs_apply_button_clicked(GtkButton *, GtkBuilder *);
+ /* Active une action native (cf. https://docs.gtk.org/gtk4/class.Window.html#actions) */
+ gtk_widget_class_add_binding_action(widget, GDK_KEY_Escape, 0 /* GDK 4.14 : GDK_NO_MODIFIER_MASK */, "window.close", NULL);
+}
/******************************************************************************
* *
-* Paramètres : store = arborescence des sections à compléter. *
-* parent = point d'insertion du parent. *
-* config = configuration globale à charger. *
-* stack = pile de composants GTK à constituer. *
-* node = noeud de description courant à traiter. *
+* Paramètres : dialog = composant GTK à initialiser. *
* *
-* Description : Ajoute un panneau de paramétrage à la boîte de dialogue. *
+* Description : Procède à l'initialisation de la fenêtre des paramètres. *
* *
* Retour : - *
* *
@@ -154,95 +130,152 @@ static void on_prefs_apply_button_clicked(GtkButton *, GtkBuilder *);
* *
******************************************************************************/
-static void add_preferences_node(GtkTreeStore *store, GtkTreeIter *parent, GGenConfig *config, GtkStack *stack, pref_node_desc_t *node)
+static void gtk_preferences_dialog_init(GtkPreferencesDialog *dialog)
{
- GtkTreeIter iter; /* Point d'insertion */
- pref_node_desc_t *child; /* Sous-élément à traiter */
+ size_t i; /* Boucle de parcours */
+ const tweak_info_t *info; /* Informations à considérer */
+ GtkListBox *navigation; /* Liste de sections à afficher*/
+ GtkTweakSection *section; /* Nouvelle section à présenter*/
+ tweak_info_t *dyn_infos; /* Informations supplémentaires*/
+ size_t dyn_count; /* Quantité de ces informations*/
+
+ tweak_info_t infos[] = {
+ TWEAK_SIMPLE_DEF("root", "Basics",
+ "security-high-symbolic", "appearance", "Appearance", GTK_TYPE_APPEARANCE_TWEAK_PANEL),
+ TWEAK_SIMPLE_DEF("root", "Basics",
+ "security-high-symbolic", "security", "Security", GTK_TYPE_SECURITY_TWEAK_PANEL),
+ };
+
+ gtk_widget_init_template(GTK_WIDGET(dialog));
- if (node->create == NULL)
+ dialog->navigations = g_hash_table_new_full(g_str_hash, g_str_equal, free, g_object_unref);
+
+ /* Chargement des sections fixes */
+
+ for (i = 0; i < ARRAY_SIZE(infos); i++)
{
- node->builder = NULL;
- node->panel = NULL;
+ info = &infos[i];
+
+ navigation = gtk_preferences_dialog_get_navigation(dialog, info->parent, true);
+ assert(navigation != NULL);
+
+ section = gtk_tweak_section_new(info);
+
+ gtk_list_box_append(navigation, GTK_WIDGET(section));
+
}
- else
+
+ /* Chargement des sections dynamiques */
+
+ dyn_infos = get_tweakable_plugins_info(&dyn_count);
+
+ for (i = 0; i < dyn_count; i++)
{
- node->panel = node->create(&node->builder);
+ info = &dyn_infos[i];
- node->load(node->builder, config);
+ navigation = gtk_preferences_dialog_get_navigation(dialog, info->parent, true);
+ assert(navigation != NULL);
- gtk_widget_show(node->panel);
+ section = gtk_tweak_section_new(info);
- gtk_stack_add_named(stack, node->panel, node->name);
+ gtk_list_box_append(navigation, GTK_WIDGET(section));
}
- gtk_tree_store_append(store, &iter, parent);
+ if (dyn_infos != NULL)
+ free(dyn_infos);
+
+ /* Affichage de la liste racine */
- gtk_tree_store_set(store, &iter,
- PLI_TITLE, _(node->title),
- PLI_PANEL, node->panel,
- -1);
+ navigation = gtk_preferences_dialog_get_navigation(dialog, "root", false);
+ assert(navigation != NULL);
- if (node->children != NULL)
- for (child = node->children; child->title != NULL; child++)
- add_preferences_node(store, &iter, config, stack, child);
+ g_signal_connect(navigation, "row-selected",
+ G_CALLBACK(gtk_preferences_dialog_on_row_selected), dialog);
+
+ gtk_scrolled_window_set_child(dialog->side_content, GTK_WIDGET(navigation));
+
+ unref_object(navigation);
}
/******************************************************************************
* *
-* Paramètres : parent = fenêtre principale de l'éditeur. *
-* outb = constructeur à détruire après usage. [OUT] *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
-* Description : Propose une boîte de dialogue pour la configuration générale.*
+* Description : Supprime toutes les références externes. *
* *
-* Retour : Adresse de la fenêtre mise en place. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GtkWidget *create_preferences_dialog(GtkWindow *parent, GtkBuilder **outb)
+static void gtk_preferences_dialog_dispose(GObject *object)
{
- GtkWidget *result; /* Fenêtre à renvoyer */
- GtkBuilder *builder; /* Constructeur utilisé */
- GGenConfig *config; /* Configuration globale */
- GtkStack *stack; /* Pile à mettre à jour */
- GtkTreeStore *store; /* Arborescence des sections */
- pref_node_desc_t *iter; /* Boucle de parcours */
- GtkTreeView *treeview; /* Arborescence principale */
+ GtkPreferencesDialog *dialog; /* Version spécialisée */
+
+ dialog = GTK_PREFERENCES_DIALOG(object);
- builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/preferences.ui");
- *outb = builder;
+ if (dialog->navigations != NULL)
+ {
+ /**
+ * Cf. documentation de g_hash_table_new_full().
+ */
+ g_hash_table_remove_all(dialog->navigations);
- result = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ g_hash_table_unref(dialog->navigations);
+ dialog->navigations = NULL;
- gtk_window_set_transient_for(GTK_WINDOW(result), parent);
+ }
- /* Intégration des différentes sections */
+ gtk_widget_dispose_template(GTK_WIDGET(dialog), GTK_TYPE_PREFERENCES_DIALOG);
+
+ G_OBJECT_CLASS(gtk_preferences_dialog_parent_class)->dispose(object);
+
+}
- config = get_main_configuration();
- stack = GTK_STACK(gtk_builder_get_object(builder, "stack"));
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- store = GTK_TREE_STORE(gtk_builder_get_object(builder, "pref_list"));
+static void gtk_preferences_dialog_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_preferences_dialog_parent_class)->finalize(object);
- for (iter = _prefs_nodes; iter->title != NULL; iter++)
- add_preferences_node(store, NULL, config, stack, iter);
+}
- treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
- gtk_tree_view_expand_all(treeview);
+/******************************************************************************
+* *
+* Paramètres : parent = fenêtre parente à surpasser. *
+* *
+* Description : Construit une boîte de dialogue pour les préférences. *
+* *
+* Retour : Adresse de la fenêtre mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- /* Connexion des signaux */
+GtkWindow *gtk_preferences_dialog_new(GtkWindow *parent)
+{
+ GtkWindow *result; /* Boite de dialogue à renvoyer*/
- gtk_builder_add_callback_symbols(builder,
- BUILDER_CALLBACK(on_prefs_selection_changed),
- BUILDER_CALLBACK(on_prefs_apply_button_clicked),
- NULL);
+ result = g_object_new(GTK_TYPE_PREFERENCES_DIALOG, NULL);
- gtk_builder_connect_signals(builder, builder);
+ if (!gtk_preferences_dialog_create(GTK_PREFERENCES_DIALOG(result), parent))
+ g_clear_object(&result);
return result;
@@ -251,79 +284,85 @@ GtkWidget *create_preferences_dialog(GtkWindow *parent, GtkBuilder **outb)
/******************************************************************************
* *
-* Paramètres : selection = sélection courante de l'arborescence des options.*
-* builder = constructeur GTK avec toutes les références. *
+* Paramètres : dialog = boîte de dialogue à initialiser pleinement. *
+* parent = fenêtre parente à surpasser. *
* *
-* Description : Affiche le panneau correspondant au noeud sélectionné. *
+* Description : Met en place la boîte de dialogue pour les préférences. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void on_prefs_selection_changed(GtkTreeSelection *selection, GtkBuilder *builder)
+bool gtk_preferences_dialog_create(GtkPreferencesDialog *dialog, GtkWindow *parent)
{
- GtkTreeModel *model; /* Gestionnaire de données */
- GtkTreeIter iter; /* Position courante */
- GtkWidget *panel; /* Panneau à mettre en avant */
- GtkStack *stack; /* Pile à mettre à jour */
-
- if (gtk_tree_selection_get_selected(selection, &model, &iter))
- {
- gtk_tree_model_get(model, &iter, PLI_PANEL, &panel, -1);
+ bool result; /* Bilan à retourner */
- stack = GTK_STACK(gtk_builder_get_object(builder, "stack"));
+ result = true;
- if (panel == NULL)
- gtk_stack_set_visible_child_name(stack, "empty");
-
- else
- {
- gtk_stack_set_visible_child(stack, panel);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
- g_object_unref(G_OBJECT(panel));
-
- }
-
- }
+ return result;
}
/******************************************************************************
* *
-* Paramètres : config = configuration globale à actualiser. *
-* node = noeud de description courant à traiter. *
+* Paramètres : dialog = boîte de dialogue à initialiser pleinement. *
+* key = désignation de la liste à fournir. *
+* create = autorisation d'une création si besoin est. *
* *
-* Description : Lance la sauvegarde d'éléments de paramétrage. *
+* Description : Fournit la liste de section désignée par un nom. *
* *
-* Retour : - *
+* Retour : Composant graphique à utiliser. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void store_preferences_node(GGenConfig *config, pref_node_desc_t *node)
+static GtkListBox *gtk_preferences_dialog_get_navigation(GtkPreferencesDialog *dialog, const char *key, bool create)
{
- pref_node_desc_t *child; /* Sous-élément à traiter */
+ GtkListBox *result; /* Instance à retourner */
+#ifndef NDEBUG
+ gboolean status; /* Bilan d'une insertion */
+#endif
- if (node->create != NULL)
- node->store(node->builder, config);
+ result = g_hash_table_lookup(dialog->navigations, key);
- if (node->children != NULL)
- for (child = node->children; child->title != NULL; child++)
- store_preferences_node(config, child);
+ if (result == NULL && create)
+ {
+ result = GTK_LIST_BOX(gtk_list_box_new());
+ g_object_ref_sink(G_OBJECT(result));
+
+ gtk_list_box_set_selection_mode(result, GTK_SELECTION_BROWSE);
+ gtk_widget_add_css_class(GTK_WIDGET(result), "navigation-sidebar");
+
+#ifndef NDEBUG
+ status = g_hash_table_insert(dialog->navigations, strdup(key), result);
+ assert(status);
+#else
+ g_hash_table_insert(dialog->navigations, key, result);
+#endif
+
+ }
+
+ if (result != NULL)
+ ref_object(result);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : button = bouton GTK à l'origine de l'opération. *
-* builder = constructeur GTK avec toutes les références. *
+* Paramètres : navigation = liste concernée par l'événement. *
+* selected = élément sélectionné (voire NULL). *
+* dialog = boîte de dialogue à initialiser pleinement. *
* *
-* Description : Sauvegarde l'ensemble des paramètres de configuration. *
+* Description : Réagit à un changement de sélection dans les sections. *
* *
* Retour : - *
* *
@@ -331,14 +370,41 @@ static void store_preferences_node(GGenConfig *config, pref_node_desc_t *node)
* *
******************************************************************************/
-static void on_prefs_apply_button_clicked(GtkButton *button, GtkBuilder *builder)
+static void gtk_preferences_dialog_on_row_selected(GtkListBox *navigation, GtkListBoxRow *selected, GtkPreferencesDialog *dialog)
{
- GGenConfig *config; /* Configuration globale */
- pref_node_desc_t *iter; /* Boucle de parcours */
+ GtkTweakSection *section; /* Nature réelle sélectionnée */
+ GType type; /* Type de panneau de config. */
+ GtkWidget *panel; /* Nouveau panneau à présenter */
+
+ if (selected != NULL)
+ {
+ if (!gtk_tweak_section_has_sub_section(GTK_TWEAK_SECTION(selected)))
+ {
+ section = GTK_TWEAK_SECTION(selected);
+
+ gtk_label_set_text(dialog->main_title, gtk_tweak_section_get_label(section));
+
+ type = gtk_tweak_section_get_panel(section);
+ panel = g_object_new(type, NULL);
- config = get_main_configuration();
+ gtk_scrolled_window_set_child(dialog->main_content, panel);
- for (iter = _prefs_nodes; iter->title != NULL; iter++)
- store_preferences_node(config, iter);
+ }
+
+ else
+ {
+
+ // TODO
+
+ }
+
+ }
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
diff --git a/src/gui/dialogs/preferences.h b/src/gui/dialogs/preferences.h
index d04af72..e291ea8 100644
--- a/src/gui/dialogs/preferences.h
+++ b/src/gui/dialogs/preferences.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * preferences.h - prototypes pour la (re)définition de l'identité de l'utilisateur
+ * preferences.h - prototypes pour la boîte de dialogue d'édition des préférences de l'utilisateur
*
- * Copyright (C) 2019 Cyrille Bagard
+ * Copyright (C) 2019-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,9 +28,17 @@
#include <gtk/gtk.h>
+#include "../../glibext/helpers.h"
-/* Propose une boîte de dialogue pour la configuration générale. */
-GtkWidget *create_preferences_dialog(GtkWindow *, GtkBuilder **);
+
+
+#define GTK_TYPE_PREFERENCES_DIALOG (gtk_preferences_dialog_get_type())
+
+DECLARE_GTYPE(GtkPreferencesDialog, gtk_preferences_dialog, GTK, PREFERENCES_DIALOG);
+
+
+/* Construit une boîte de dialogue pour les préférences. */
+GtkWindow *gtk_preferences_dialog_new(GtkWindow *);
diff --git a/src/gui/dialogs/preferences.ui b/src/gui/dialogs/preferences.ui
index 251ef46..950242a 100644
--- a/src/gui/dialogs/preferences.ui
+++ b/src/gui/dialogs/preferences.ui
@@ -1,156 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.21.0 -->
<interface>
- <requires lib="gtk+" version="3.20"/>
- <object class="GtkTreeStore" id="pref_list">
- <columns>
- <!-- column-name title -->
- <column type="gchararray"/>
- <!-- column-name panel -->
- <column type="GObject"/>
- </columns>
- </object>
- <object class="GtkDialog" id="window">
- <property name="can_focus">False</property>
- <property name="title" translatable="yes">General preferences</property>
- <property name="modal">True</property>
- <property name="default_width">800</property>
- <property name="default_height">500</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkBox">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox">
- <property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="button1">
- <property name="label">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button2">
- <property name="label">gtk-apply</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- <signal name="clicked" handler="on_prefs_apply_button_clicked" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
+
+ <template class="GtkPreferencesDialog" parent="GtkWindow">
+
+ <property name="default-width">980</property>
+ <property name="default-height">640</property>
+ <property name="modal">true</property>
+ <property name="resizable">true</property>
+
+ <child type="titlebar">
+ <object class="GtkBox">
+ <child>
+ <object class="GtkHeaderBar" id="sidebar-header">
+ <property name="decoration-layout">:</property>
+
+ <property name="title-widget">
+ <object class="GtkLabel" id="side_title">
+ <property name="label" translatable="yes">Parameters</property>
+ <property name="single-line-mode">True</property>
+ <property name="ellipsize">end</property>
+ <property name="width-chars">5</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </property>
+
+ <child type="start">
+ <object class="GtkToggleButton">
+ <property name="icon-name">edit-find-symbolic</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Séparation centrale -->
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ <property name="css-name">sidebar</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkHeaderBar" id="main-header">
+ <property name="hexpand">1</property>
+
+ <property name="title-widget">
+ <object class="GtkLabel" id="main_title">
+ <property name="label" translatable="yes"></property>
+ <property name="single-line-mode">True</property>
+ <property name="ellipsize">end</property>
+ <property name="width-chars">5</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </property>
+
+ </object>
+ </child>
+ </object>
</child>
+
<child>
- <object class="GtkPaned">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="position">200</property>
- <property name="wide_handle">True</property>
- <child>
- <object class="GtkScrolledWindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="shadow_type">in</property>
+ <object class="GtkBox">
<child>
- <object class="GtkTreeView" id="treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="model">pref_list</property>
- <property name="headers_visible">False</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection">
- <signal name="changed" handler="on_prefs_selection_changed" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">column</property>
- <child>
- <object class="GtkCellRendererText"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- </child>
- </object>
+ <object class="GtkScrolledWindow" id="side_content">
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">automatic</property>
+ </object>
+ </child>
+
+ <!-- Séparation centrale -->
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ <property name="css-name">sidebar</property>
+ </object>
</child>
- </object>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkStack" id="stack">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
+
<child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="name">empty</property>
- </packing>
+ <object class="GtkScrolledWindow" id="main_content">
+ <property name="hexpand">1</property>
+ <property name="vexpand">1</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">automatic</property>
+ </object>
</child>
- </object>
- <packing>
- <property name="resize">True</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
+ </object>
</child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">button1</action-widget>
- <action-widget response="-10">button2</action-widget>
- </action-widgets>
- <child>
- <placeholder/>
- </child>
- </object>
+
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="sidebar-header"/>
+ <widget name="side_content"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="main-header"/>
+ <widget name="main_content"/>
+ </widgets>
+ </object>
+
+ </template>
</interface>
diff --git a/src/gui/dialogs/prefs/Makefile.am b/src/gui/dialogs/prefs/Makefile.am
new file mode 100644
index 0000000..50bc3c8
--- /dev/null
+++ b/src/gui/dialogs/prefs/Makefile.am
@@ -0,0 +1,34 @@
+
+BUILT_SOURCES = resources.h resources.c
+
+noinst_LTLIBRARIES = libguidialogsprefs.la
+
+UI_FILES = \
+ appearance.ui \
+ security.ui
+
+libguidialogsprefs_la_SOURCES = \
+ appearance-int.h \
+ appearance.h appearance.c \
+ resources.h resources.c \
+ security-int.h \
+ security.h security.c
+
+libguidialogsprefs_la_CFLAGS = $(LIBGTK4_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libguidialogsprefs_la_SOURCES:%c=)
+
+
+resources.c: gresource.xml $(UI_FILES)
+ glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name gui_dialogs_prefs gresource.xml
+
+resources.h: gresource.xml
+ glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name gui_dialogs_prefs gresource.xml
+
+
+CLEANFILES = resources.h resources.c
+
+EXTRA_DIST = gresource.xml $(UI_FILES)
diff --git a/src/gui/dialogs/prefs/appearance-int.h b/src/gui/dialogs/prefs/appearance-int.h
new file mode 100644
index 0000000..886a562
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * appearance-int.h - définitions internes pour la configuration des paramètres liés aux apparences
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFS_APPEARANCE_INT_H
+#define _GUI_DIALOGS_PREFS_APPEARANCE_INT_H
+
+
+#include "appearance.h"
+
+
+
+/* Composant d'édition des paramètres liés aux apparences (instance) */
+struct _GtkAppearanceTweakPanel
+{
+ GtkBox parent; /* A laisser en premier */
+
+ /* Disposition des panneaux */
+
+ GSettings *tiles_settings; /* Configuration sollicitée */
+
+ GtkWidget *layout_preview; /* Zone d'aperçu de dispositon*/
+
+ GtkWidget *top_panel; /* Composant d'aperçu #1 */
+ GtkWidget *left_panel; /* Composant d'aperçu #2 */
+ GtkWidget *right_panel; /* Composant d'aperçu #3 */
+ GtkWidget *bottom_panel; /* Composant d'aperçu #4 */
+
+ GtkCheckButton *left_top_reach; /* Paramètre de disposition #1 */
+ GtkCheckButton *left_bottom_reach; /* Paramètre de disposition #2 */
+ GtkCheckButton *right_top_reach; /* Paramètre de disposition #3 */
+ GtkCheckButton *right_bottom_reach; /* Paramètre de disposition #4 */
+
+};
+
+/* Composant d'édition des paramètres liés aux apparences (classe) */
+struct _GtkAppearanceTweakPanelClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_DIALOGS_PREFS_APPEARANCE_INT_H */
diff --git a/src/gui/dialogs/prefs/appearance.c b/src/gui/dialogs/prefs/appearance.c
new file mode 100644
index 0000000..a8585fa
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance.c
@@ -0,0 +1,251 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * appearance.c - configuration des paramètres liés aux apparences
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "appearance.h"
+
+
+#include "appearance-int.h"
+#include "../../../gtkext/grid.h"
+#include "../../../gtkext/helpers.h"
+
+
+
+/* Procède à l'initialisation de classe des configurations. */
+static void gtk_appearance_tweak_panel_class_init(GtkAppearanceTweakPanelClass *);
+
+/* Procède à l'initialisation des configurations de sécurité. */
+static void gtk_appearance_tweak_panel_init(GtkAppearanceTweakPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_appearance_tweak_panel_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_appearance_tweak_panel_finalize(GObject *);
+
+/* Réagit à un changement de paramètre de configuration. */
+static void gtk_appearance_tweak_panel_on_tiles_settings_changed(GSettings *, const gchar *, GtkAppearanceTweakPanel *);
+
+/* Change la disposition des panneaux de la fenêtre principale. */
+static void gtk_appearance_tweak_panel_on_panel_reach_toggled(GtkCheckButton *, GtkAppearanceTweakPanel *);
+
+
+/* Indique le type du composant de configuration des notes. */
+G_DEFINE_TYPE(GtkAppearanceTweakPanel, gtk_appearance_tweak_panel, GTK_TYPE_BOX);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de classe des configurations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_class_init(GtkAppearanceTweakPanelClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_appearance_tweak_panel_dispose;
+ object->finalize = gtk_appearance_tweak_panel_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/prefs/appearance.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_appearance_tweak_panel_on_panel_reach_toggled));
+
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, layout_preview);
+
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, top_panel);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, left_panel);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, right_panel);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, bottom_panel);
+
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, left_top_reach);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, left_bottom_reach);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, right_top_reach);
+ gtk_widget_class_bind_template_child(widget, GtkAppearanceTweakPanel, right_bottom_reach);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation des configurations de sécurité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_init(GtkAppearanceTweakPanel *panel)
+{
+ LayoutReachOptions options; /* Détails de disposition */
+
+ gtk_widget_init_template(GTK_WIDGET(panel));
+
+ panel->tiles_settings = g_settings_new_with_path("re.chrysalide.framework.tiledgrid",
+ "/re/chrysalide/framework/gui/tiles/");
+
+ options = g_settings_get_flags(panel->tiles_settings, "layout");
+
+ gtk_check_button_set_active(panel->left_top_reach, options & LRO_LEFT_TOP_REACH);
+ gtk_check_button_set_active(panel->left_bottom_reach, options & LRO_LEFT_BOTTOM_REACH);
+ gtk_check_button_set_active(panel->right_top_reach, options & LRO_RIGHT_TOP_REACH);
+ gtk_check_button_set_active(panel->right_bottom_reach, options & LRO_RIGHT_BOTTOM_REACH);
+
+ gtk_appearance_tweak_panel_on_tiles_settings_changed(panel->tiles_settings, "layout", panel);
+
+ g_signal_connect(panel->tiles_settings, "changed",
+ G_CALLBACK(gtk_appearance_tweak_panel_on_tiles_settings_changed), panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_dispose(GObject *object)
+{
+ GtkAppearanceTweakPanel *panel; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_APPEARANCE_TWEAK_PANEL);
+
+ panel = GTK_APPEARANCE_TWEAK_PANEL(object);
+
+ g_clear_object(&panel->tiles_settings);
+
+ G_OBJECT_CLASS(gtk_appearance_tweak_panel_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_appearance_tweak_panel_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : settings = ensemble de paramètres connaissant une évolution. *
+* key = identifiant du paramètre ayant changé. *
+* panel = panneau de paramétrage concerné par l'appel. *
+* *
+* Description : Réagit à un changement de paramètre de configuration. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_on_tiles_settings_changed(GSettings *settings, const gchar *key, GtkAppearanceTweakPanel *panel)
+{
+ LayoutReachOptions options; /* Détails de disposition */
+
+ if (strcmp(key, "layout") == 0)
+ {
+ options = g_settings_get_flags(panel->tiles_settings, "layout");
+
+ apply_tiling_grid_layout(GTK_GRID(panel->layout_preview), options, (GtkWidget *[]) {
+ panel->top_panel, panel->left_panel, panel->right_panel, panel->bottom_panel
+ });
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = composant radio dont l'état vient de basculer. *
+* panel = panneau d'édition des préférences courant. *
+* *
+* Description : Change la disposition des panneaux de la fenêtre principale. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_appearance_tweak_panel_on_panel_reach_toggled(GtkCheckButton *button, GtkAppearanceTweakPanel *panel)
+{
+ gboolean left_top_reach; /* Paramètre de disposition #1 */
+ gboolean left_bottom_reach; /* Paramètre de disposition #2 */
+ gboolean right_top_reach; /* Paramètre de disposition #3 */
+ gboolean right_bottom_reach; /* Paramètre de disposition #4 */
+ LayoutReachOptions options; /* Options à appliquer */
+
+ /* Récupération des indications */
+
+ left_top_reach = gtk_check_button_get_active(panel->left_top_reach);
+ left_bottom_reach = gtk_check_button_get_active(panel->left_bottom_reach);
+ right_top_reach = gtk_check_button_get_active(panel->right_top_reach);
+ right_bottom_reach = gtk_check_button_get_active(panel->right_bottom_reach);
+
+ /* Conversion et application */
+
+ options = LRO_NONE;
+
+ if (left_top_reach) options |= LRO_LEFT_TOP_REACH;
+ if (left_bottom_reach) options |= LRO_LEFT_BOTTOM_REACH;
+ if (right_top_reach) options |= LRO_RIGHT_TOP_REACH;
+ if (right_bottom_reach) options |= LRO_RIGHT_BOTTOM_REACH;
+
+ g_settings_set_flags(panel->tiles_settings, "layout", options);
+
+}
diff --git a/src/gui/dialogs/prefs/appearance.h b/src/gui/dialogs/prefs/appearance.h
new file mode 100644
index 0000000..916b194
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * appearance.h - prototypes pour la configuration des paramètres liés aux apparences
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFS_APPEARANCE_H
+#define _GUI_DIALOGS_PREFS_APPEARANCE_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_APPEARANCE_TWEAK_PANEL (gtk_appearance_tweak_panel_get_type())
+
+DECLARE_GTYPE(GtkAppearanceTweakPanel, gtk_appearance_tweak_panel, GTK, APPEARANCE_TWEAK_PANEL);
+
+
+
+#endif /* _GUI_DIALOGS_PREFS_APPEARANCE_H */
diff --git a/src/gui/dialogs/prefs/appearance.ui b/src/gui/dialogs/prefs/appearance.ui
new file mode 100644
index 0000000..3410115
--- /dev/null
+++ b/src/gui/dialogs/prefs/appearance.ui
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkAppearanceTweakPanel" parent="GtkBox">
+
+ <property name="orientation">vertical</property>
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">20</property>
+ <property name="margin-bottom">20</property>
+ <property name="spacing">10</property>
+
+ <!-- Disposition des panneaux -->
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Layout</property>
+ <property name="use-markup">true</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="heading"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Layout defines the global panel organization of the main window.</property>
+ <property name="wrap">true</property>
+ <property name="use-markup">true</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <!-- Aperçu -->
+
+ <child>
+ <object class="GtkGrid" id="layout_preview">
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="row-spacing">5</property>
+ <property name="column-spacing">5</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">200</property>
+ <property name="width-request">300</property>
+
+ <child>
+ <object class="GtkFrame" id="top_panel">
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">20</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="left_panel">
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">50</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame">
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="right_panel">
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">50</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="bottom_panel">
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">50</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">3</property>
+ </layout>
+ <style>
+ <class name="view"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <!-- Options -->
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <property name="spacing">10</property>
+
+ <child>
+ <object class="GtkCheckButton" id="left_top_reach">
+ <property name="label">Left panels reach the top of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCheckButton" id="left_bottom_reach">
+ <property name="label">Left panels reach the bottom of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCheckButton" id="right_top_reach">
+ <property name="label">Right panels reach the top of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCheckButton" id="right_bottom_reach">
+ <property name="label">Right panels reach the bottom of the window</property>
+ <property name="active">false</property>
+ <signal name="toggled" handler="gtk_appearance_tweak_panel_on_panel_reach_toggled"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gui/dialogs/prefs/gresource.xml b/src/gui/dialogs/prefs/gresource.xml
new file mode 100644
index 0000000..ad0f97f
--- /dev/null
+++ b/src/gui/dialogs/prefs/gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/re/chrysalide/framework/gui/dialogs/prefs">
+ <file compressed="true">appearance.ui</file>
+ <file compressed="true">security.ui</file>
+ </gresource>
+</gresources>
diff --git a/src/gui/dialogs/prefs/security-int.h b/src/gui/dialogs/prefs/security-int.h
new file mode 100644
index 0000000..be7867c
--- /dev/null
+++ b/src/gui/dialogs/prefs/security-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * security-int.h - définitions internes pour la configuration des paramètres liés à la sécurité
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFS_SECURITY_INT_H
+#define _GUI_DIALOGS_PREFS_SECURITY_INT_H
+
+
+#include "security.h"
+#include "../../../glibext/secstorage.h"
+
+
+
+/* Composant d'édition des paramètres de sécurité (instance) */
+struct _GtkSecurityTweakPanel
+{
+ GtkBox parent; /* A laisser en premier */
+
+ /* Stockage sécurisé */
+
+ GSecretStorage *storage; /* Stockage des secrets */
+
+ GtkWidget *current_primary_passwd; /* Mot de passe courant */
+
+ GtkWidget *new_primary_passwd; /* Nouveau mot de passe */
+ GtkWidget *new_primary_passwd_lbl; /* Etiquette associée */
+ GtkWidget *new_primary_passwd_2; /* Nouveau mot de passe (#2) */
+ GtkWidget *new_primary_passwd_2_lbl; /* Etiquette associée (#2) */
+
+ GtkWidget *set_password; /* Bouton de définition de mdp */
+ GtkWidget *change_password; /* Bouton de changement de mdp */
+ GtkWidget *remove_password; /* Bouton de suppression de mdp*/
+
+};
+
+/* Composant d'édition des paramètres de sécurité (classe) */
+struct _GtkSecurityTweakPanelClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_DIALOGS_PREFS_SECURITY_INT_H */
diff --git a/src/gui/dialogs/prefs/security.c b/src/gui/dialogs/prefs/security.c
new file mode 100644
index 0000000..2b82339
--- /dev/null
+++ b/src/gui/dialogs/prefs/security.c
@@ -0,0 +1,400 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * security.c - configuration des paramètres liés à la sécurité
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "security.h"
+
+
+#include <i18n.h>
+
+
+#include "security-int.h"
+#include "../../../core/global.h"
+#include "../../../core/logs.h"
+#include "../../../gtkext/helpers.h"
+
+
+
+/* ---------------------- GESTION DE L'ENSEMBLE DES PARAMETRES ---------------------- */
+
+
+/* Procède à l'initialisation de classe des configurations. */
+static void gtk_security_tweak_panel_class_init(GtkSecurityTweakPanelClass *);
+
+/* Procède à l'initialisation des configurations de sécurité. */
+static void gtk_security_tweak_panel_init(GtkSecurityTweakPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_security_tweak_panel_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_security_tweak_panel_finalize(GObject *);
+
+
+
+/* ---------------------- CONSERVATION SECURISEE DE PARAMETRES ---------------------- */
+
+
+/* Initalise la partie relative au stockage sécurisé. */
+static void gtk_security_tweak_panel_init_secret_storage(GtkSecurityTweakPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_security_tweak_panel_dispose_secret_storage(GtkSecurityTweakPanel *);
+
+/* Note le changement de verrouillage du stockage sécurisé. */
+static void gtk_security_tweak_panel_on_secret_storage_lock_update(GSecretStorage *, GtkSecurityTweakPanel *);
+
+/* Réagit à un changement dans l'édition d'un mot de passe. */
+static void gtk_security_tweak_panel_on_new_passwords_changed(GtkEditable *, GtkSecurityTweakPanel *);
+
+/* Réagit à une demande de création de mot de passe. */
+static void gtk_security_tweak_panel_on_set_password_clicked(GtkButton *, GtkSecurityTweakPanel *);
+
+/* Réagit à une demande de changement de mot de passe. */
+static void gtk_security_tweak_panel_on_change_password_clicked(GtkButton *, GtkSecurityTweakPanel *);
+
+/* Réagit à une demande de suppression de mot de passe. */
+static void gtk_security_tweak_panel_on_remove_password_clicked(GtkButton *, GtkSecurityTweakPanel *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION DE L'ENSEMBLE DES PARAMETRES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type du composant d'édition des paramètres de sécurité. */
+G_DEFINE_TYPE(GtkSecurityTweakPanel, gtk_security_tweak_panel, GTK_TYPE_BOX);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de classe des configurations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_class_init(GtkSecurityTweakPanelClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_security_tweak_panel_dispose;
+ object->finalize = gtk_security_tweak_panel_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/prefs/security.ui");
+
+ /* Stockage sécurisé */
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_security_tweak_panel_on_new_passwords_changed));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_security_tweak_panel_on_set_password_clicked));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_security_tweak_panel_on_change_password_clicked));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_security_tweak_panel_on_remove_password_clicked));
+
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, current_primary_passwd);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, new_primary_passwd);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, new_primary_passwd_lbl);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, new_primary_passwd_2);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, new_primary_passwd_2_lbl);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, set_password);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, change_password);
+ gtk_widget_class_bind_template_child(widget, GtkSecurityTweakPanel, remove_password);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation des configurations de sécurité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_init(GtkSecurityTweakPanel *panel)
+{
+ gtk_widget_init_template(GTK_WIDGET(panel));
+
+ gtk_security_tweak_panel_init_secret_storage(panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_dispose(GObject *object)
+{
+ GtkSecurityTweakPanel *panel; /* Version spécialisée */
+
+ panel = GTK_SECURITY_TWEAK_PANEL(object);
+
+ gtk_security_tweak_panel_dispose_secret_storage(panel);
+
+ gtk_widget_dispose_template(GTK_WIDGET(panel), GTK_TYPE_SECURITY_TWEAK_PANEL);
+
+ G_OBJECT_CLASS(gtk_security_tweak_panel_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_security_tweak_panel_parent_class)->finalize(object);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONSERVATION SECURISEE DE PARAMETRES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = composant GTK à initialiser. *
+* *
+* Description : Initalise la partie relative au stockage sécurisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_init_secret_storage(GtkSecurityTweakPanel *panel)
+{
+ panel->storage = get_secret_storage();
+
+ g_signal_connect(panel->storage, "lock-update",
+ G_CALLBACK(gtk_security_tweak_panel_on_secret_storage_lock_update), panel);
+
+ gtk_security_tweak_panel_on_secret_storage_lock_update(panel->storage, panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_dispose_secret_storage(GtkSecurityTweakPanel *panel)
+{
+ if (panel->storage != NULL)
+ g_signal_handlers_disconnect_by_func(panel->storage,
+ gtk_security_tweak_panel_on_secret_storage_lock_update, panel);
+
+ g_clear_object(&panel->storage);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gardien des secrets impliqué. *
+* panel = support de la partie relative au stockage sécurisé.*
+* *
+* Description : Note le changement de verrouillage du stockage sécurisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_on_secret_storage_lock_update(GSecretStorage *storage, GtkSecurityTweakPanel *panel)
+{
+ bool has_key; /* Existence d'une clef ? */
+
+ has_key = g_secret_storage_has_key(panel->storage);
+
+ gtk_widget_set_visible(panel->new_primary_passwd, has_key);
+ gtk_widget_set_visible(panel->new_primary_passwd_lbl, has_key);
+
+ gtk_widget_set_visible(panel->new_primary_passwd_2, has_key);
+ gtk_widget_set_visible(panel->new_primary_passwd_2_lbl, has_key);
+
+ gtk_widget_set_visible(panel->set_password, !has_key);
+ gtk_widget_set_visible(panel->change_password, has_key);
+ gtk_widget_set_visible(panel->remove_password, has_key);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : editable = zone de saisie bouton GTK concerné par l'appel. *
+* panel = support de la partie liée au stockage sécurisé. *
+* *
+* Description : Réagit à un changement dans l'édition d'un mot de passe. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_on_new_passwords_changed(GtkEditable *editable, GtkSecurityTweakPanel *panel)
+{
+ const char *new_passwd; /* Nouveau mot de passe #1 */
+ const char *new_passwd_2; /* Nouveau mot de passe #2 */
+ bool status; /* Bilan de l'opération */
+
+ new_passwd = gtk_editable_get_text(GTK_EDITABLE(panel->new_primary_passwd));
+
+ new_passwd_2 = gtk_editable_get_text(GTK_EDITABLE(panel->new_primary_passwd_2));
+
+ status = (strcmp(new_passwd, new_passwd_2) == 0);
+
+ gtk_widget_set_sensitive(panel->change_password, status);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton GTK concerné par l'appel. *
+* panel = support de la partie relative au stockage sécurisé. *
+* *
+* Description : Réagit à une demande de création de mot de passe. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_on_set_password_clicked(GtkButton *button, GtkSecurityTweakPanel *panel)
+{
+ const char *passwd; /* Mot de passe à considérer */
+ bool status; /* Bilan de l'opération */
+
+ passwd = gtk_editable_get_text(GTK_EDITABLE(panel->current_primary_passwd));
+
+ status = g_secret_storage_set_password(panel->storage, passwd);
+
+ log_variadic_message(LMT_INFO, _("Setting password for secret storage: %s"),
+ status ? _("success") : _("failed"));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton GTK concerné par l'appel. *
+* panel = support de la partie relative au stockage sécurisé. *
+* *
+* Description : Réagit à une demande de changement de mot de passe. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_on_change_password_clicked(GtkButton *button, GtkSecurityTweakPanel *panel)
+{
+ const char *old_passwd; /* Ancien mot de passe */
+ const char *new_passwd; /* Nouveau mot de passe */
+ bool status; /* Bilan de l'opération */
+
+ old_passwd = gtk_editable_get_text(GTK_EDITABLE(panel->current_primary_passwd));
+
+ new_passwd = gtk_editable_get_text(GTK_EDITABLE(panel->new_primary_passwd));
+
+ status = g_secret_storage_change_password(panel->storage, old_passwd, new_passwd);
+
+ log_variadic_message(LMT_INFO, _("Changed password for secret storage: %s"),
+ status ? _("success") : _("failed"));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton GTK concerné par l'appel. *
+* panel = support de la partie relative au stockage sécurisé. *
+* *
+* Description : Réagit à une demande de suppression de mot de passe. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_security_tweak_panel_on_remove_password_clicked(GtkButton *button, GtkSecurityTweakPanel *panel)
+{
+ const char *passwd; /* Mot de passe à considérer */
+ bool status; /* Bilan de l'opération */
+
+ passwd = gtk_editable_get_text(GTK_EDITABLE(panel->current_primary_passwd));
+
+ status = g_secret_storage_remove_password(panel->storage, passwd);
+
+ log_variadic_message(LMT_INFO, _("Removed password for secret storage: %s"),
+ status ? _("success") : _("failed"));
+
+}
diff --git a/src/gui/dialogs/prefs/security.h b/src/gui/dialogs/prefs/security.h
new file mode 100644
index 0000000..206a123
--- /dev/null
+++ b/src/gui/dialogs/prefs/security.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * security.h - prototypes pour la configuration des paramètres liés à la sécurité
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_PREFS_SECURITY_H
+#define _GUI_DIALOGS_PREFS_SECURITY_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_SECURITY_TWEAK_PANEL (gtk_security_tweak_panel_get_type())
+
+DECLARE_GTYPE(GtkSecurityTweakPanel, gtk_security_tweak_panel, GTK, SECURITY_TWEAK_PANEL);
+
+
+
+#endif /* _GUI_DIALOGS_PREFS_SECURITY_H */
diff --git a/src/gui/dialogs/prefs/security.ui b/src/gui/dialogs/prefs/security.ui
new file mode 100644
index 0000000..ccf2d39
--- /dev/null
+++ b/src/gui/dialogs/prefs/security.ui
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkSecurityTweakPanel" parent="GtkBox">
+
+ <property name="orientation">vertical</property>
+
+ <!-- Conservation de paramètres sécurisée -->
+ <child>
+ <object class="GtkGrid">
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">20</property>
+ <property name="margin-bottom">20</property>
+ <property name="row-spacing">10</property>
+ <property name="column-spacing">10</property>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Secret storage</property>
+ <property name="use-markup">true</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ </layout>
+ <style>
+ <class name="heading"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Configuration may handle sensitive data (such as passwords or API keys) which can be saved in plain text or stored encrypted using a Primary Password.
+
+If encryption is activated, entering the Primary Password will be asked on need once per session.</property>
+ <property name="wrap">true</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <!-- Mot de passe courant -->
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Enter current password:</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkPasswordEntry" id="current_primary_passwd">
+ <property name="hexpand">true</property>
+ <property name="show-peek-icon">true</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Nouveau mot de passe -->
+
+ <child>
+ <object class="GtkLabel" id="new_primary_passwd_lbl">
+ <property name="label">Enter new password:</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkPasswordEntry" id="new_primary_passwd">
+ <property name="hexpand">true</property>
+ <property name="show-peek-icon">true</property>
+ <signal name="changed" handler="gtk_security_tweak_panel_on_new_passwords_changed"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Confirmation de mot de passe -->
+
+ <child>
+ <object class="GtkLabel" id="new_primary_passwd_2_lbl">
+ <property name="label">Re-enter new password:</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkPasswordEntry" id="new_primary_passwd_2">
+ <property name="hexpand">true</property>
+ <property name="show-peek-icon">true</property>
+ <signal name="changed" handler="gtk_security_tweak_panel_on_new_passwords_changed"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Boutons de contrôle -->
+
+ <child>
+ <object class="GtkBox">
+ <property name="halign">center</property>
+ <property name="homogeneous">true</property>
+ <property name="spacing">8</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">2</property>
+ </layout>
+
+ <child>
+ <object class="GtkButton" id="set_password">
+ <property name="label">Set</property>
+ <signal name="clicked" handler="gtk_security_tweak_panel_on_set_password_clicked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="change_password">
+ <property name="label">Change</property>
+ <signal name="clicked" handler="gtk_security_tweak_panel_on_change_password_clicked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="remove_password">
+ <property name="label">Remove</property>
+ <signal name="clicked" handler="gtk_security_tweak_panel_on_remove_password_clicked"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gui/gresource.xml b/src/gui/gresource.xml
index 011281d..91d9bc9 100644
--- a/src/gui/gresource.xml
+++ b/src/gui/gresource.xml
@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
- <gresource prefix="/org/chrysalide/gui">
- <file compressed="true">editor.ui</file>
+ <gresource prefix="/re/chrysalide/framework/gui">
+ <file compressed="true">style.css</file>
+ <file compressed="true">window.ui</file>
+ </gresource>
+ <gresource prefix="/re/chrysalide/framework/images">
+ <file compressed="true" alias="chrysalide-logo.svg">../../pixmaps/chrysalide-logo.svg</file>
</gresource>
</gresources>
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index 83e173b..ecff6c7 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -3,7 +3,7 @@ DEFAULT_INCLUDES = -idirafter. -I$(top_builddir)
BUILT_SOURCES = resources.h resources.c
-noinst_LTLIBRARIES = libguipanels.la
+noinst_LTLIBRARIES = libguipanels4.la # libguipanels.la
UI_FILES = \
bintree.ui \
@@ -11,11 +11,9 @@ UI_FILES = \
errors.ui \
glance.ui \
history.ui \
- log.ui \
regedit.ui \
strings.ui \
- symbols.ui \
- welcome.ui
+ symbols.ui
libguipanels_la_SOURCES = \
bintree.h bintree.c \
@@ -23,25 +21,50 @@ libguipanels_la_SOURCES = \
errors.h errors.c \
glance.h glance.c \
history.h history.c \
- log.h log.c \
regedit.h regedit.c \
resources.h resources.c \
strings.h strings.c \
symbols.h symbols.c \
updating-int.h \
updating.h updating.c \
- view.h view.c \
- welcome.h welcome.c
+ view.h view.c
libguipanels_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+IMG_PATH = ../../../data/images
+
+RES_FILES = \
+ binary.ui \
+ binary-params.ui \
+ $(IMG_PATH)/binfile-symbolic.svg \
+ logs.ui \
+ logs-col-icon.ui \
+ logs-col-message.ui \
+ welcome.ui \
+ welcome-hints.txt \
+ $(IMG_PATH)/tipoftheday-symbolic.svg
+
+libguipanels4_la_SOURCES = \
+ binary-int.h \
+ binary.h binary.c \
+ binary-params-int.h \
+ binary-params.h binary-params.c \
+ logs-int.h \
+ logs.h logs.c \
+ resources.h resources.c \
+ welcome-int.h \
+ welcome.h welcome.c
+
+libguipanels4_la_CFLAGS = $(LIBGTK4_CFLAGS)
+
+
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libguipanels_la_SOURCES:%c=)
-resources.c: gresource.xml $(UI_FILES)
+resources.c: gresource.xml $(RES_FILES)
glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name gui_panels gresource.xml
resources.h: gresource.xml
@@ -50,4 +73,4 @@ resources.h: gresource.xml
CLEANFILES = resources.h resources.c
-EXTRA_DIST = gresource.xml $(UI_FILES)
+EXTRA_DIST = gresource.xml $(RES_FILES)
diff --git a/src/gui/panels/binary-int.h b/src/gui/panels/binary-int.h
new file mode 100644
index 0000000..5116f5c
--- /dev/null
+++ b/src/gui/panels/binary-int.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binary-int.h - prototypes internes pour le panneau d'affichage de contenus d'un binaire, bruts ou non
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 _GUI_PANELS_BINARY_INT_H
+#define _GUI_PANELS_BINARY_INT_H
+
+
+#include "binary.h"
+#include "../../gtkext/panel-int.h"
+
+
+
+/* Panneau d'accueil par défaut (instance) */
+struct _GtkBinaryPanel
+{
+ GtkTiledPanel parent; /* A laisser en premier */
+
+ GtkScrolledWindow *hex_scroll; /* Défilement pour contenu #0 */
+
+};
+
+/* Panneau d'accueil par défaut (classe) */
+struct _GtkBinaryPanelClass
+{
+ GtkTiledPanelClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_PANELS_BINARY_INT_H */
diff --git a/src/gui/panels/binary-params-int.h b/src/gui/panels/binary-params-int.h
new file mode 100644
index 0000000..0fbef24
--- /dev/null
+++ b/src/gui/panels/binary-params-int.h
@@ -0,0 +1,50 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binary-params-int.h - définitions internes pour l'édition des paramètres initiaux d'un chargement de binaire
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_PANELS_BINARY_PARAMS_INT_H
+#define _GUI_PANELS_BINARY_PARAMS_INT_H
+
+
+#include "binary-params.h"
+
+
+
+/* Composant pour les paramètres de chargement d'un binaire (instance) */
+struct _GtkBinaryParameters
+{
+ GtkGrid parent; /* A laisser en premier */
+
+ GtkEntry *filename; /* CHemin d'un binaire */
+
+};
+
+/* Composant pour les paramètres de chargement d'un binaire (classe) */
+struct _GtkBinaryParametersClass
+{
+ GtkGridClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_PANELS_BINARY_PARAMS_INT_H */
diff --git a/src/gui/panels/binary-params.c b/src/gui/panels/binary-params.c
new file mode 100644
index 0000000..1059761
--- /dev/null
+++ b/src/gui/panels/binary-params.c
@@ -0,0 +1,178 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binary-params.c - édition des paramètres initiaux d'un chargement de binaire
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "binary-params.h"
+
+
+#include "binary.h"
+#include "binary-params-int.h"
+#include "../window.h"
+#include "../../analysis/contents/file.h"
+#include "../../gtkext/helpers.h"
+
+
+
+/* Initialise la classe des composants d'édition de paramètres. */
+static void gtk_binary_parameters_class_init(GtkBinaryParametersClass *);
+
+/* Initialise une instance de composant d'édition de paramètres. */
+static void gtk_binary_parameters_init(GtkBinaryParameters *);
+
+/* Supprime toutes les références externes. */
+static void gtk_binary_parameters_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_binary_parameters_finalize(GObject *);
+
+/* Ouvre une boîte de dialogue pour récupérer un fichier. */
+static void gtk_binary_parameters_on_new_file_entry_icon_release(GtkEntry *, GtkEntryIconPosition, GtkBinaryParameters *);
+
+
+
+/* Détermine le type du composant d'édition des paramètres de chargement. */
+G_DEFINE_TYPE(GtkBinaryParameters, gtk_binary_parameters, GTK_TYPE_GRID);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des composants d'édition de paramètres. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_parameters_class_init(GtkBinaryParametersClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_binary_parameters_dispose;
+ object->finalize = gtk_binary_parameters_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/panels/binary-params.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_binary_parameters_on_new_file_entry_icon_release));
+
+ gtk_widget_class_bind_template_child(widget, GtkBinaryParameters, filename);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : params = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de composant d'édition de paramètres.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_parameters_init(GtkBinaryParameters *params)
+{
+ gtk_widget_init_template(GTK_WIDGET(params));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_parameters_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_BINARY_PARAMETERS);
+
+ G_OBJECT_CLASS(gtk_binary_parameters_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_parameters_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_binary_parameters_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = zone de saisie concernée par l'appel. *
+* icon_pos = position de l'icone incrustée dans la zone. *
+* params = composant d'édition des paramètres. *
+* *
+* Description : Ouvre une boîte de dialogue pour récupérer un fichier. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_parameters_on_new_file_entry_icon_release(GtkEntry *entry, GtkEntryIconPosition icon_pos, GtkBinaryParameters *params)
+{
+ GtkRoot *root; /* Racine du composant */
+ GBinContent *content; /* Contenu binaire à afficher */
+ GtkTiledPanel *tiled; /* Panneau d'affichage complet */
+
+ root = gtk_widget_get_root(GTK_WIDGET(entry));
+
+ content = g_file_content_new("/bin/id");
+
+ tiled = gtk_binary_panel_new_for_content(content);
+
+ unref_object(content);
+
+ gtk_framework_window_add(GTK_FRAMEWORK_WINDOW(root), tiled);
+
+}
diff --git a/src/gui/panels/binary-params.h b/src/gui/panels/binary-params.h
new file mode 100644
index 0000000..450da25
--- /dev/null
+++ b/src/gui/panels/binary-params.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binary-params.h - prototypes pour l'édition des paramètres initiaux d'un chargement de binaire
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_PANELS_BINARY_PARAMS_H
+#define _GUI_PANELS_BINARY_PARAMS_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_BINARY_PARAMETERS (gtk_binary_parameters_get_type())
+
+DECLARE_GTYPE(GtkBinaryParameters, gtk_binary_parameters, GTK, BINARY_PARAMETERS);
+
+
+
+#endif /* _GUI_PANELS_BINARY_PARAMS_H */
diff --git a/src/gui/panels/binary-params.ui b/src/gui/panels/binary-params.ui
new file mode 100644
index 0000000..dcbaf7c
--- /dev/null
+++ b/src/gui/panels/binary-params.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkBinaryParameters" parent="GtkGrid">
+ <property name="margin-bottom">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">12</property>
+ <property name="column-spacing">12</property>
+ <property name="row-spacing">8</property>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Load and analyze a new file:</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkEntry" id="filename">
+ <property name="secondary-icon-name">document-open-symbolic</property>
+ <property name="placeholder-text">File location</property>
+ <property name="hexpand">TRUE</property>
+ <property name="hexpand-set">TRUE</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="background"/>
+ </style>
+ <signal name="icon-release" handler="gtk_binary_parameters_on_new_file_entry_icon_release"/>
+ </object>
+ </child>
+
+ </template>
+
+</interface>
diff --git a/src/gui/panels/binary.c b/src/gui/panels/binary.c
new file mode 100644
index 0000000..f58c06b
--- /dev/null
+++ b/src/gui/panels/binary.c
@@ -0,0 +1,195 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binary.c - panneau d'affichage de contenus d'un binaire, bruts ou non
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 "binary.h"
+
+
+#include "binary-int.h"
+#include "../../gtkext/helpers.h"
+#include "../../gtkext/hexview.h"
+
+
+
+/* ------------------------- COEUR D'UN PANNEAU D'AFFICHAGE ------------------------- */
+
+
+/* Initialise la classe des panneaux pour binaires. */
+static void gtk_binary_panel_class_init(GtkBinaryPanelClass *);
+
+/* Initialise une instance de panneau pour binaire. */
+static void gtk_binary_panel_init(GtkBinaryPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_binary_panel_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_binary_panel_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COEUR D'UN PANNEAU D'AFFICHAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un panneau d'affichage de contenus d'un binaire. */
+G_DEFINE_TYPE(GtkBinaryPanel, gtk_binary_panel, GTK_TYPE_TILED_PANEL);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux pour binaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_panel_class_init(GtkBinaryPanelClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_binary_panel_dispose;
+ object->finalize = gtk_binary_panel_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/panels/binary.ui");
+
+ gtk_widget_class_bind_template_child(widget, GtkBinaryPanel, hex_scroll);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau pour binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_panel_init(GtkBinaryPanel *panel)
+{
+ gtk_widget_init_template(GTK_WIDGET(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_panel_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_BINARY_PANEL);
+
+ G_OBJECT_CLASS(gtk_binary_panel_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_binary_panel_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_binary_panel_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu brut à exposer. *
+* *
+* Description : Crée une nouvelle instance de panneau pour binaire. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkTiledPanel *gtk_binary_panel_new_for_content(GBinContent *content)
+{
+ GtkTiledPanel *result; /* Instance à retourner */
+ GtkHexView *view; /* Composant d'affichage */
+
+ result = g_object_new(GTK_TYPE_BINARY_PANEL, NULL);
+
+ view = gtk_hex_view_new(content);
+ gtk_scrolled_window_set_child(GTK_BINARY_PANEL(result)->hex_scroll, GTK_WIDGET(view));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
+
+
+
+
diff --git a/src/gui/panels/binary.h b/src/gui/panels/binary.h
new file mode 100644
index 0000000..26f8a7d
--- /dev/null
+++ b/src/gui/panels/binary.h
@@ -0,0 +1,48 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binary.h - prototypes pour le panneau d'accueil par défaut
+ *
+ * Copyright (C) 2012-2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 _GUI_PANELS_BINARY_H
+#define _GUI_PANELS_BINARY_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../analysis/content.h"
+#include "../../glibext/helpers.h"
+#include "../../gtkext/panel.h"
+
+
+
+#define GTK_TYPE_BINARY_PANEL (gtk_binary_panel_get_type())
+
+DECLARE_GTYPE(GtkBinaryPanel, gtk_binary_panel, GTK, BINARY_PANEL);
+
+
+/* Crée une nouvelle instance de panneau pour binaire. */
+GtkTiledPanel *gtk_binary_panel_new_for_content(GBinContent *);
+
+
+
+#endif /* _GUI_PANELS_BINARY_H */
diff --git a/src/gui/panels/binary.ui b/src/gui/panels/binary.ui
new file mode 100644
index 0000000..a34c409
--- /dev/null
+++ b/src/gui/panels/binary.ui
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkBinaryPanel" parent="GtkTiledPanel">
+ <child>
+ <object class="GtkScrolledWindow" id="hex_scroll">
+ <property name="hscrollbar-policy">automatic</property>
+ <property name="vscrollbar-policy">automatic</property>
+ <property name="hexpand">TRUE</property>
+ <property name="vexpand">TRUE</property>
+ <property name="has-frame">0</property>
+ </object>
+ </child>
+ </template>
+
+</interface>
diff --git a/src/gui/panels/gresource.xml b/src/gui/panels/gresource.xml
index d996ef1..2765b25 100644
--- a/src/gui/panels/gresource.xml
+++ b/src/gui/panels/gresource.xml
@@ -1,20 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
- <gresource prefix="/org/chrysalide/gui/panels">
- <file compressed="true">../../../pixmaps/tbutton_list_view.png</file>
- <file compressed="true">../../../pixmaps/tbutton_tree_view.png</file>
- <file compressed="true">../../../pixmaps/tbutton_collapse.png</file>
- <file compressed="true">../../../pixmaps/tbutton_expand.png</file>
- <file compressed="true">../../../pixmaps/symbol_class_classic.png</file>
- <file compressed="true">bintree.ui</file>
- <file compressed="true">bookmarks.ui</file>
- <file compressed="true">errors.ui</file>
- <file compressed="true">glance.ui</file>
- <file compressed="true">history.ui</file>
- <file compressed="true">log.ui</file>
- <file compressed="true">regedit.ui</file>
- <file compressed="true">strings.ui</file>
- <file compressed="true">symbols.ui</file>
+ <gresource prefix="/re/chrysalide/framework/gui/panels">
+ <file compressed="true">binary.ui</file>
+ <file compressed="true">binary-params.ui</file>
+ <file compressed="true">logs.ui</file>
+ <file compressed="true">logs-col-icon.ui</file>
+ <file compressed="true">logs-col-message.ui</file>
<file compressed="true">welcome.ui</file>
+ <file compressed="true">welcome-hints.txt</file>
+ </gresource>
+ <gresource prefix="/re/chrysalide/framework/gui/icons/scalable/actions">
+ <file compressed="true" alias="binfile-symbolic.svg">../../../data/images/binfile-symbolic.svg</file>
+ <file compressed="true" alias="tipoftheday-symbolic.svg">../../../data/images/tipoftheday-symbolic.svg</file>
</gresource>
</gresources>
diff --git a/src/gui/panels/log.c b/src/gui/panels/log.c
deleted file mode 100644
index d11fbd2..0000000
--- a/src/gui/panels/log.c
+++ /dev/null
@@ -1,451 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * log.c - panneau d'affichage des messages système
- *
- * Copyright (C) 2012-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 "log.h"
-
-
-#include <malloc.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <gtk/gtk.h>
-
-
-#include "../panel-int.h"
-#include "../core/panels.h"
-#include "../../gtkext/easygtk.h"
-#include "../../gtkext/named.h"
-
-
-
-/* Colonnes de la liste des messages */
-typedef enum _LogColumn
-{
- LGC_PICTURE, /* Image de représentation */
- LGC_STRING, /* Chaîne de caractères */
-
- LGC_COUNT /* Nombre de colonnes */
-
-} LogColumn;
-
-
-/* Paramètres à transmettre pour un affichage */
-typedef struct _log_data
-{
- GPanelItem *item; /* Intermédiaire mis en place */
- LogMessageType type; /* Type de message à afficher */
- char *msg; /* Contenu du message */
-
-} log_data;
-
-
-/* Panneau d'accueil (instance) */
-struct _GLogPanel
-{
- GPanelItem parent; /* A laisser en premier */
-
-};
-
-
-/* Panneau d'accueil (classe) */
-struct _GLogPanelClass
-{
- GPanelItemClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des panneaux d'affichage des messages. */
-static void g_log_panel_class_init(GLogPanelClass *);
-
-/* Initialise une instance de panneau d'affichage des messages. */
-static void g_log_panel_init(GLogPanel *);
-
-/* Supprime toutes les références externes. */
-static void g_log_panel_dispose(GLogPanel *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_log_panel_finalize(GLogPanel *);
-
-/* Fournit le nom interne attribué à l'élément réactif. */
-static char *g_log_panel_class_get_key(const GLogPanelClass *);
-
-/* Fournit une indication sur la personnalité du panneau. */
-static PanelItemPersonality g_log_panel_class_get_personality(const GLogPanelClass *);
-
-/* Indique le chemin initial de la localisation d'un panneau. */
-static char *g_log_panel_class_get_path(const GLogPanelClass *);
-
-/* Indique la définition d'un éventuel raccourci clavier. */
-static char *g_log_panel_class_get_key_bindings(const GLogPanelClass *);
-
-/* Affiche un message dans le journal des messages système. */
-static gboolean log_message(log_data *);
-
-
-
-/* Indique le type défini pour un panneau d'affichage de messages. */
-G_DEFINE_TYPE(GLogPanel, g_log_panel, G_TYPE_PANEL_ITEM);
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à initialiser. *
-* *
-* Description : Initialise la classe des panneaux d'affichage des messages. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_class_init(GLogPanelClass *class)
-{
- GObjectClass *object; /* Autre version de la classe */
- GEditorItemClass *item; /* Encore une autre vision... */
- GPanelItemClass *panel; /* Version parente de la classe*/
-
- object = G_OBJECT_CLASS(class);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_log_panel_dispose;
- object->finalize = (GObjectFinalizeFunc)g_log_panel_finalize;
-
- item = G_EDITOR_ITEM_CLASS(class);
-
- item->get_key = (get_item_key_fc)g_log_panel_class_get_key;
-
- panel = G_PANEL_ITEM_CLASS(class);
-
- panel->get_personality = (get_panel_personality_fc)g_log_panel_class_get_personality;
- panel->get_path = (get_panel_path_fc)g_log_panel_class_get_path;
- panel->get_bindings = (get_panel_bindings_fc)g_log_panel_class_get_key_bindings;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance à initialiser. *
-* *
-* Description : Initialise une instance de panneau d'affichage des messages. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_init(GLogPanel *panel)
-{
- GPanelItem *pitem; /* Version parente du panneau */
-
- /* Eléments de base */
-
- pitem = G_PANEL_ITEM(panel);
-
- pitem->widget = G_NAMED_WIDGET(gtk_built_named_widget_new_for_panel(_("Messages"),
- _("Misc information"),
- PANEL_LOG_ID));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_dispose(GLogPanel *panel)
-{
- G_OBJECT_CLASS(g_log_panel_parent_class)->dispose(G_OBJECT(panel));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_log_panel_finalize(GLogPanel *panel)
-{
- G_OBJECT_CLASS(g_log_panel_parent_class)->finalize(G_OBJECT(panel));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Fournit le nom interne attribué à l'élément réactif. *
-* *
-* Retour : Désignation (courte) de l'élément de l'éditeur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_log_panel_class_get_key(const GLogPanelClass *class)
-{
- char *result; /* Description à renvoyer */
-
- result = strdup(PANEL_LOG_ID);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Fournit une indication sur la personnalité du panneau. *
-* *
-* Retour : Identifiant lié à la nature unique du panneau. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PanelItemPersonality g_log_panel_class_get_personality(const GLogPanelClass *class)
-{
- PanelItemPersonality result; /* Personnalité à retourner */
-
- result = PIP_PERSISTENT_SINGLETON;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Indique le chemin initial de la localisation d'un panneau. *
-* *
-* Retour : Chemin fixé associé à la position initiale. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_log_panel_class_get_path(const GLogPanelClass *class)
-{
- char *result; /* Emplacement à retourner */
-
- result = strdup("Ms");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Indique la définition d'un éventuel raccourci clavier. *
-* *
-* Retour : Description d'un raccourci ou NULL si aucun de défini. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_log_panel_class_get_key_bindings(const GLogPanelClass *class)
-{
- char *result; /* Emplacement à retourner */
-
- result = strdup("<Shift>F1");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un panneau d'affichage des messages système. *
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPanelItem *g_log_panel_new(void)
-{
- GPanelItem *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_LOG_PANEL, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
-* type = espèce du message à ajouter. *
-* msg = message à faire apparaître à l'écran. *
-* *
-* Description : Affiche un message dans le journal des messages système. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_log_panel_add_message(GLogPanel *panel, LogMessageType type, const char *msg)
-{
- log_data *data; /* Paramètres à joindre */
-
- data = calloc(1, sizeof(log_data));
-
- data->item = G_PANEL_ITEM(panel);
- data->type = type;
- data->msg = strdup(msg);
-
- g_object_ref(G_OBJECT(data->item));
-
- g_main_context_invoke(NULL, (GSourceFunc)log_message, data);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : data = paramètres destinés à l'affichage d'un message. *
-* *
-* Description : Affiche un message dans le journal des messages système. *
-* *
-* Retour : - *
-* *
-* Remarques : Cette fonction, et c'est tout son intérêt, est toujours *
-* exécutée dans le contexte GTK principal. *
-* *
-******************************************************************************/
-
-static gboolean log_message(log_data *data)
-{
- GtkBuilder *builder; /* Constructeur utilisé */
- GtkListStore *store; /* Modèle de gestion */
- GtkTreeIter iter; /* Point d'insertion */
- GtkTreeView *treeview; /* Affichage de la liste */
-
- builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(G_PANEL_ITEM(data->item)->widget));
-
- /* Mise en place du message */
-
- store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
-
- gtk_list_store_append(store, &iter);
-
- switch (data->type)
- {
- case LMT_INFO:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-info",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_PROCESS:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-execute",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_WARNING:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-dialog-warning",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_BAD_BINARY:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-dialog-warning",
- LGC_STRING, data->msg,
- -1);
- break;
-
- case LMT_ERROR:
- case LMT_EXT_ERROR:
- gtk_list_store_set(store, &iter,
- LGC_PICTURE, "gtk-dialog-error",
- LGC_STRING, data->msg,
- -1);
- break;
-
- default:
- gtk_list_store_set(store, &iter,
- LGC_STRING, data->msg,
- -1);
- break;
-
- }
-
- /* Défilement pour pointer à l'affichage */
-
- treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
-
- scroll_to_treeview_iter(treeview, GTK_TREE_MODEL(store), &iter);
-
- g_object_unref(G_OBJECT(builder));
-
- /* Nettoyage de la mémoire */
-
- g_object_unref(G_OBJECT(data->item));
-
- free(data->msg);
-
- free(data);
-
- return G_SOURCE_REMOVE;
-
-}
diff --git a/src/gui/panels/log.h b/src/gui/panels/log.h
deleted file mode 100644
index 4d155a2..0000000
--- a/src/gui/panels/log.h
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * log.h - prototypes pour le panneau d'affichage des messages système
- *
- * Copyright (C) 2012-2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#ifndef _GUI_PANELS_LOG_H
-#define _GUI_PANELS_LOG_H
-
-
-#include <i18n.h>
-
-
-#include "../panel.h"
-#include "../../core/logs.h"
-
-
-
-#define PANEL_LOG_ID "log"
-
-
-#define G_TYPE_LOG_PANEL g_log_panel_get_type()
-#define G_LOG_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_log_panel_get_type(), GLogPanel))
-#define G_IS_LOG_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_log_panel_get_type()))
-#define G_LOG_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LOG_PANEL, GLogPanelClass))
-#define G_IS_LOG_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LOG_PANEL))
-#define G_LOG_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LOG_PANEL, GLogPanelClass))
-
-
-/* Panneau d'affichage de messages (instance) */
-typedef struct _GLogPanel GLogPanel;
-
-/* Panneau d'affichage de messages (classe) */
-typedef struct _GLogPanelClass GLogPanelClass;
-
-
-
-/* Indique le type défini pour un panneau d'affichage de messages. */
-GType g_log_panel_get_type(void);
-
-/* Crée un panneau d'affichage des messages système. */
-GPanelItem *g_log_panel_new(void);
-
-/* Affiche un message dans le journal des messages système. */
-void g_log_panel_add_message(GLogPanel *, LogMessageType, const char *);
-
-
-
-#endif /* _GUI_PANELS_LOG_H */
diff --git a/src/gui/panels/log.ui b/src/gui/panels/log.ui
deleted file mode 100644
index 4ffe96c..0000000
--- a/src/gui/panels/log.ui
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.21.0 -->
-<interface>
- <requires lib="gtk+" version="3.20"/>
- <object class="GtkListStore" id="store">
- <columns>
- <!-- column-name picture -->
- <column type="gchararray"/>
- <!-- column-name string -->
- <column type="gchararray"/>
- </columns>
- </object>
- <object class="GtkOffscreenWindow">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkScrolledWindow" id="box">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="model">store</property>
- <property name="headers_visible">False</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection"/>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">picture</property>
- <child>
- <object class="GtkCellRendererPixbuf"/>
- <attributes>
- <attribute name="stock-id">0</attribute>
- </attributes>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">string</property>
- <child>
- <object class="GtkCellRendererText"/>
- <attributes>
- <attribute name="markup">1</attribute>
- </attributes>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="titlebar">
- <placeholder/>
- </child>
- </object>
-</interface>
diff --git a/src/gui/panels/logs-col-icon.ui b/src/gui/panels/logs-col-icon.ui
new file mode 100644
index 0000000..6463e84
--- /dev/null
+++ b/src/gui/panels/logs-col-icon.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkImage">
+ <binding name="icon-name">
+ <lookup name="icon-name" type="GLogEntry">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </property>
+
+ </template>
+
+</interface>
diff --git a/src/gui/panels/logs-col-message.ui b/src/gui/panels/logs-col-message.ui
new file mode 100644
index 0000000..49839e4
--- /dev/null
+++ b/src/gui/panels/logs-col-message.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="use-markup">true</property>
+ <binding name="label">
+ <lookup name="message" type="GLogEntry">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </property>
+
+ </template>
+
+</interface>
diff --git a/src/gui/panels/logs-int.h b/src/gui/panels/logs-int.h
new file mode 100644
index 0000000..692c1b4
--- /dev/null
+++ b/src/gui/panels/logs-int.h
@@ -0,0 +1,53 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logs-int.h - prototypes internes pour le panneau d'affichage des messages système
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 _GUI_PANELS_LOGS_INT_H
+#define _GUI_PANELS_LOGS_INT_H
+
+
+#include "logs.h"
+#include "../../gtkext/panel-int.h"
+
+
+
+/* Panneau d'affichage de messages (instance) */
+struct _GtkLogsPanel
+{
+ GtkTiledPanel parent; /* A laisser en premier */
+
+ GListStore *store; /* Liste des eléments conservés*/
+ GtkWidget *list; /* Composant d'affichage */
+
+};
+
+/* Panneau d'affichage de messages (classe) */
+struct _GtkLogsPanelClass
+{
+ GtkTiledPanelClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_PANELS_LOGS_INT_H */
diff --git a/src/gui/panels/logs.c b/src/gui/panels/logs.c
new file mode 100644
index 0000000..399c4c0
--- /dev/null
+++ b/src/gui/panels/logs.c
@@ -0,0 +1,227 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logs.c - panneau d'affichage des messages système
+ *
+ * Copyright (C) 2012-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 "logs.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "logs-int.h"
+#include "../../gtkext/helpers.h"
+
+
+
+/* ------------------------- COEUR D'UN PANNEAU D'AFFICHAGE ------------------------- */
+
+
+/* Initialise la classe des panneaux d'affichage des journaux. */
+static void gtk_logs_panel_class_init(GtkLogsPanelClass *);
+
+/* Initialise une instance de panneau d'affichage des journaux. */
+static void gtk_logs_panel_init(GtkLogsPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_logs_panel_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_logs_panel_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique l'emplacement par défaut pour un affichage. */
+static char *gtk_logs_panel_get_default_path(const GtkTiledPanel *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COEUR D'UN PANNEAU D'AFFICHAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un panneau d'accueil. */
+G_DEFINE_TYPE(GtkLogsPanel, gtk_logs_panel, GTK_TYPE_TILED_PANEL);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux d'affichage des journaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_class_init(GtkLogsPanelClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+ GtkTiledPanelClass *panel; /* Classe parente */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_logs_panel_dispose;
+ object->finalize = gtk_logs_panel_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ g_type_ensure(G_TYPE_LOG_ENTRY);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/panels/logs.ui");
+
+ //gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_logs_panel_on_selected_rows_changed));
+
+ gtk_widget_class_bind_template_child(widget, GtkLogsPanel, store);
+ gtk_widget_class_bind_template_child(widget, GtkLogsPanel, list);
+
+ panel = GTK_TILED_PANEL_CLASS(class);
+
+ panel->get_default_path = gtk_logs_panel_get_default_path;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau d'affichage des journaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_init(GtkLogsPanel *panel)
+{
+ GtkWidget *headers; /* Composant à cacher */
+
+ gtk_widget_init_template(GTK_WIDGET(panel));
+
+ /**
+ * Retrait des entêtes de colonne de l'affichage.
+ */
+
+ headers = gtk_widget_get_first_child(panel->list);
+
+ gtk_widget_set_visible(headers, FALSE);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_LOGS_PANEL);
+
+ G_OBJECT_CLASS(gtk_logs_panel_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_logs_panel_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_logs_panel_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* entry = élément de journalisation à intégrer. *
+* *
+* Description : Affiche un message dans le journal des messages système. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_log_panel_add_message(GtkLogsPanel *panel, GLogEntry *entry)
+{
+ g_list_store_append(panel->store, entry);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
+* *
+* Description : Indique l'emplacement par défaut pour un affichage. *
+* *
+* Retour : Chemin représenté ou NULL pour l'emplacement "M" par défaut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *gtk_logs_panel_get_default_path(const GtkTiledPanel *panel)
+{
+ char *result; /* Chemin à retourner */
+
+ result = strdup("S");
+
+ return result;
+
+}
diff --git a/src/gui/panels/logs.h b/src/gui/panels/logs.h
new file mode 100644
index 0000000..a8b902b
--- /dev/null
+++ b/src/gui/panels/logs.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logs.h - prototypes pour le panneau d'affichage des messages système
+ *
+ * Copyright (C) 2012-2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 _GUI_PANELS_LOGS_H
+#define _GUI_PANELS_LOGS_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../glibext/helpers.h"
+#include "../../glibext/log.h"
+
+
+
+#define GTK_TYPE_LOGS_PANEL (gtk_logs_panel_get_type())
+
+DECLARE_GTYPE(GtkLogsPanel, gtk_logs_panel, GTK, LOGS_PANEL);
+
+
+/* Affiche un message dans le journal des messages système. */
+void g_log_panel_add_message(GtkLogsPanel *, GLogEntry *);
+
+
+
+#endif /* _GUI_PANELS_LOGS_H */
diff --git a/src/gui/panels/logs.ui b/src/gui/panels/logs.ui
new file mode 100644
index 0000000..ba920cd
--- /dev/null
+++ b/src/gui/panels/logs.ui
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <object class="GtkNoSelection" id="noselection">
+ <property name="model">
+ <object class="GListStore" id="store">
+ <property name="item-type">GLogEntry</property>
+ </object>
+ </property>
+ </object>
+
+ <template class="GtkLogsPanel" parent="GtkTiledPanel">
+
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">automatic</property>
+ <property name="vscrollbar-policy">automatic</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <property name="has-frame">0</property>
+
+ <child>
+ <object class="GtkColumnView" id="list">
+ <property name="vexpand">true</property>
+ <property name="model">noselection</property>
+
+ <child>
+ <object class="GtkColumnViewColumn">
+ <property name="title"></property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="resource">/re/chrysalide/framework/gui/panels/logs-col-icon.ui</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkColumnViewColumn">
+ <property name="expand">true</property>
+ <property name="title">Message</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="resource">/re/chrysalide/framework/gui/panels/logs-col-message.ui</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+
+</interface>
diff --git a/src/gui/panels/welcome-hints.txt b/src/gui/panels/welcome-hints.txt
new file mode 100644
index 0000000..a35ea64
--- /dev/null
+++ b/src/gui/panels/welcome-hints.txt
@@ -0,0 +1,23 @@
+Chrysalide's GUI offers launchers at startup in order to run main activities quickly.
+
+Once an activity is selected, options get displayed and allow some tunning before starting new processes.
+
+Such options are usually saved between runs.
+
+
+There is no need to install Chrysalide on your system if you only want to give it a try.
+
+Just compile the source code and run the program from there.
+
+
+Chrysalide can be used in external Python scripts by setting PYTHONPATH to the directory containing the 'pychrysalide.so' file. For instance:
+
+ cd plugins/pychrysa/.libs/
+ export PYTHONPATH=$PWD
+
+Then run the interpreter suitable to your configuration (debug or release):
+
+ python3-dbg -c 'import pychrysalide ; print(pychrysalide.mod_version())'
+
+
+All the configuration files for Chrysalide are located in $HOME/.config/chrysalide/. \ No newline at end of file
diff --git a/src/gui/panels/welcome-int.h b/src/gui/panels/welcome-int.h
new file mode 100644
index 0000000..206bc2c
--- /dev/null
+++ b/src/gui/panels/welcome-int.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * welcome-int.h - prototypes internes pour le panneau d'accueil par défaut
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 _GUI_PANELS_WELCOME_INT_H
+#define _GUI_PANELS_WELCOME_INT_H
+
+
+#include "welcome.h"
+#include "../../gtkext/panel-int.h"
+
+
+
+/* Panneau d'accueil par défaut (instance) */
+struct _GtkWelcomePanel
+{
+ GtkTiledPanel parent; /* A laisser en premier */
+
+ GtkListBox *list; /* Liste de lanceurs */
+ GtkStack *properties; /* Premières propriétés */
+
+ GtkWidget *def_child; /* Contenu par défaut */
+ GtkLabel *hints; /* Affichage d'astuces du jour */
+ GtkWidget *other_child; /* Autre contenu, alternatif */
+
+ gchar **raw_hints; /* Liste d'astuces */
+ guint raw_count; /* Taille de cette liste */
+ guint cur_hint; /* Position dans le parcours */
+
+};
+
+/* Panneau d'accueil par défaut (classe) */
+struct _GtkWelcomePanelClass
+{
+ GtkTiledPanelClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GUI_PANELS_WELCOME_INT_H */
diff --git a/src/gui/panels/welcome.c b/src/gui/panels/welcome.c
index 60593d1..6e8763b 100644
--- a/src/gui/panels/welcome.c
+++ b/src/gui/panels/welcome.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* welcome.c - panneau d'accueil par défaut
*
- * Copyright (C) 2012-2019 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,130 +26,63 @@
#include <assert.h>
-#include <malloc.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <i18n.h>
-
-
-#include "../panel-int.h"
-#include "../core/global.h"
-#include "../../common/cpp.h"
-#include "../../common/io.h"
-#include "../../common/net.h"
+#include "welcome-int.h"
+#include "../core/panels.h"
#include "../../common/shuffle.h"
-#include "../../core/global.h"
-#include "../../core/params.h"
-#include "../../core/paths.h"
-#include "../../gtkext/easygtk.h"
-#include "../../gtkext/named.h"
-
-
-
-/* Panneau d'accueil par défaut (instance) */
-struct _GWelcomePanel
-{
- GPanelItem parent; /* A laisser en premier */
+#include "../../gtkext/helpers.h"
- cairo_surface_t *background; /* Fond pour astuces */
- char **tips; /* Liste de toutes les astuces */
- size_t count; /* Quantité d'astuces */
- size_t current; /* Indice de l'astuce courante */
-
- bool uorigin; /* Origine de l'affichage */
-
- gulong sig_id; /* Connexion par signal */
-
-};
-
-/* Panneau d'accueil par défaut (classe) */
-struct _GWelcomePanelClass
-{
- GPanelItemClass parent; /* A laisser en premier */
-};
-
-
-/* Colonnes de la liste des messages */
-typedef enum _RecentProjectColumn
-{
- RPC_VALID, /* Validité de l'entrée */
- RPC_FULLPATH, /* Chemin d'accès à un projet */
-
- RPC_COUNT /* Nombre de colonnes */
-
-} RecentProjectColumn;
+/* ------------------------- COEUR D'UN PANNEAU D'AFFICHAGE ------------------------- */
/* Initialise la classe des panneaux d'accueil par défaut. */
-static void g_welcome_panel_class_init(GWelcomePanelClass *);
+static void gtk_welcome_panel_class_init(GtkWelcomePanelClass *);
/* Initialise une instance de panneau d'accueil par défaut. */
-static void g_welcome_panel_init(GWelcomePanel *);
+static void gtk_welcome_panel_init(GtkWelcomePanel *);
/* Supprime toutes les références externes. */
-static void g_welcome_panel_dispose(GWelcomePanel *);
+static void gtk_welcome_panel_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_welcome_panel_finalize(GWelcomePanel *);
+static void gtk_welcome_panel_finalize(GObject *);
-/* Fournit le nom interne attribué à l'élément réactif. */
-static char *g_welcome_panel_class_get_key(const GWelcomePanelClass *);
+/* Réagit à un changement de sélection de la liste de panneaux. */
+static void gtk_welcome_panel_on_selected_rows_changed(GtkListBox *, GtkWelcomePanel *);
-/* Fournit une indication sur la personnalité du panneau. */
-static PanelItemPersonality g_welcome_panel_class_get_personality(const GWelcomePanelClass *);
+/* Réagit à une demande d'affichage de l'astuce précédente. */
+static void gtk_welcome_panel_on_prev_hint_clicked(GtkButton *, GtkWelcomePanel *);
-/* Indique le chemin initial de la localisation d'un panneau. */
-static char *g_welcome_panel_class_get_path(const GWelcomePanelClass *);
+/* Réagit à une demande d'affichage de l'astuce suivante. */
+static void gtk_welcome_panel_on_next_hint_clicked(GtkButton *, GtkWelcomePanel *);
-/* Place un panneau dans l'ensemble affiché. */
-static void g_welcome_panel_dock(GWelcomePanel *);
-/* Charge l'ensemble des astuces. */
-static void g_welcome_panel_load_tips(GWelcomePanel *);
-/* Assure le dessin du fond de la bulle d'astuce. */
-static gboolean on_tip_background_draw(GtkWidget *, cairo_t *, GWelcomePanel *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Réagit à la demande d'étude d'un nouveau binaire. */
-static void on_new_binary_clicked(GtkButton *, GWelcomePanel *);
-/* Actualise au besoin la liste des projets récents. */
-static void on_recent_list_changed(GtkRecentManager *, GWelcomePanel *);
-/* Recharge une liste à jour des projets récents. */
-static void g_welcome_panel_reload_project_list(GWelcomePanel *, GtkRecentManager *);
-/* Réagit à une sélection décidée d'un projet particulier. */
-static void on_row_activated_for_projects(GtkTreeView *, GtkTreePath *, GtkTreeViewColumn *, GWelcomePanel *);
-/* Enregistre les conditions d'affichage du panneau d'accueil. */
-static void on_startup_toggled(GtkToggleButton *, GWelcomePanel *);
-/* Consulte les versions existantes et affiche une conclusion. */
-static void g_welcome_panel_check_version(GWelcomePanel *);
-/* Affiche l'astuce précédente dans la liste globale. */
-static void on_tip_previous_clicked(GtkButton *, GWelcomePanel *);
-/* Affiche l'astuce suivante dans la liste globale. */
-static void on_tip_next_clicked(GtkButton *, GWelcomePanel *);
-/* Actualise l'affichage des astuces. */
-static void g_welcome_panel_refresh_tip(GWelcomePanel *);
+/* ---------------------------------------------------------------------------------- */
+/* COEUR D'UN PANNEAU D'AFFICHAGE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un panneau d'accueil. */
-G_DEFINE_TYPE(GWelcomePanel, g_welcome_panel, G_TYPE_PANEL_ITEM);
+G_DEFINE_TYPE(GtkWelcomePanel, gtk_welcome_panel, GTK_TYPE_TILED_PANEL);
/******************************************************************************
* *
-* Paramètres : klass = classe à initialiser. *
+* Paramètres : class = classe à initialiser. *
* *
* Description : Initialise la classe des panneaux d'accueil par défaut. *
* *
@@ -159,28 +92,28 @@ G_DEFINE_TYPE(GWelcomePanel, g_welcome_panel, G_TYPE_PANEL_ITEM);
* *
******************************************************************************/
-static void g_welcome_panel_class_init(GWelcomePanelClass *klass)
+static void gtk_welcome_panel_class_init(GtkWelcomePanelClass *class)
{
GObjectClass *object; /* Autre version de la classe */
- GEditorItemClass *item; /* Encore une autre vision... */
- GPanelItemClass *panel; /* Version parente de classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
- object = G_OBJECT_CLASS(klass);
+ object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_welcome_panel_dispose;
- object->finalize = (GObjectFinalizeFunc)g_welcome_panel_finalize;
+ object->dispose = gtk_welcome_panel_dispose;
+ object->finalize = gtk_welcome_panel_finalize;
- item = G_EDITOR_ITEM_CLASS(klass);
+ widget = GTK_WIDGET_CLASS(class);
- item->get_key = (get_item_key_fc)g_welcome_panel_class_get_key;
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/panels/welcome.ui");
- panel = G_PANEL_ITEM_CLASS(klass);
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_welcome_panel_on_selected_rows_changed));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_welcome_panel_on_prev_hint_clicked));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_welcome_panel_on_next_hint_clicked));
- panel->get_personality = (get_panel_personality_fc)g_welcome_panel_class_get_personality;
- panel->dock_at_startup = gtk_panel_item_class_return_false;
- panel->get_path = (get_panel_path_fc)g_welcome_panel_class_get_path;
-
- panel->ack_dock = (ack_undock_process_fc)g_welcome_panel_dock;
+ gtk_widget_class_bind_template_child(widget, GtkWelcomePanel, list);
+ gtk_widget_class_bind_template_child(widget, GtkWelcomePanel, properties);
+ gtk_widget_class_bind_template_child(widget, GtkWelcomePanel, def_child);
+ gtk_widget_class_bind_template_child(widget, GtkWelcomePanel, hints);
}
@@ -197,93 +130,81 @@ static void g_welcome_panel_class_init(GWelcomePanelClass *klass)
* *
******************************************************************************/
-static void g_welcome_panel_init(GWelcomePanel *panel)
+static void gtk_welcome_panel_init(GtkWelcomePanel *panel)
{
- GPanelItem *pitem; /* Version parente du panneau */
- GtkBuilder *builder; /* Constructeur utilisé */
- GtkTreeView *treeview; /* Affichage de la liste */
- GtkCellRenderer *renderer; /* Moteur de rendu de colonne */
- GtkTreeViewColumn *column; /* Colonne de la liste */
- GtkToggleButton *button; /* Bouton à bascule à traiter */
- bool state; /* Etat de la coche à définir */
- gchar *filename; /* Chemin d'accès à une image */
- GtkRecentManager *manager; /* Gestionnaire global */
-
- /* Eléments de base */
-
- pitem = G_PANEL_ITEM(panel);
-
- pitem->widget = G_NAMED_WIDGET(gtk_built_named_widget_new_for_panel(_("Welcome"),
- _("Welcome panel"),
- PANEL_WELCOME_ID));
-
- panel->uorigin = !gtk_panel_item_class_dock_at_startup(G_PANEL_ITEM_GET_CLASS(pitem));
+ GBytes *bytes; /* Données brutes de ressource */
+ const gchar *data; /* Données brutes natives */
+ int min; /* Taille à gauche minimale */
+ GtkConstraintLayout *layout; /* Disposition fixant la taille*/
+ GtkConstraint *constraint; /* Contrainte à considérer */
- /* Représentation graphique */
+ gtk_widget_init_template(GTK_WIDGET(panel));
- builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(pitem->widget));
+ panel->other_child = NULL;
- /* Liste des projets récents */
+ /* Chargement des astuces */
- treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+ bytes = g_resources_lookup_data("/re/chrysalide/framework/gui/panels/welcome-hints.txt",
+ G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ assert(bytes != NULL);
- column = gtk_tree_view_column_new();
- gtk_tree_view_append_column(treeview, column);
- gtk_tree_view_set_expander_column(treeview, column);
+ data = g_bytes_get_data(bytes, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "markup", RPC_FULLPATH);
+ panel->raw_hints = g_strsplit(data, "\n\n\n", -1);
- /* Affichage au démarrage ? */
+ g_bytes_unref(bytes);
- button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "startup"));
+ panel->raw_count = g_strv_length(panel->raw_hints);
+ assert(panel->raw_count > 0);
- g_generic_config_get_value(get_main_configuration(), MPK_WELCOME_STARTUP, &state);
+ panel->cur_hint = 0;
- gtk_toggle_button_set_active(button, state);
+ /* Constitution de la liste des démarreurs */
- /* Chargement de l'image de fond */
+ populate_framework_panel_launcher_list(panel->list);
- filename = find_pixmap_file("tipoftheday.png");
+ /* Dimensionnement de la zone d'astuces */
- panel->background = cairo_image_surface_create_from_png(filename);
+ gtk_widget_measure(GTK_WIDGET(panel->list), GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
- g_free(filename);
+ if (min > 150)
+ min -= 150;
- /* Connexion des signaux */
+ layout = GTK_CONSTRAINT_LAYOUT(gtk_widget_get_layout_manager(GTK_WIDGET(panel->hints)));
- gtk_builder_add_callback_symbols(builder,
- BUILDER_CALLBACK(on_tip_background_draw),
- BUILDER_CALLBACK(on_new_binary_clicked),
- BUILDER_CALLBACK(on_row_activated_for_projects),
- BUILDER_CALLBACK(on_startup_toggled),
- BUILDER_CALLBACK(on_tip_previous_clicked),
- BUILDER_CALLBACK(on_tip_next_clicked),
- NULL);
+ gtk_constraint_layout_remove_all_constraints(layout);
- gtk_builder_connect_signals(builder, panel);
+ constraint = gtk_constraint_new_constant(NULL,
+ GTK_CONSTRAINT_ATTRIBUTE_LEFT,
+ GTK_CONSTRAINT_RELATION_EQ,
+ 0,
+ GTK_CONSTRAINT_STRENGTH_REQUIRED);
+ gtk_constraint_layout_add_constraint(layout, constraint);
- g_object_unref(G_OBJECT(builder));
+ constraint = gtk_constraint_new_constant(NULL,
+ GTK_CONSTRAINT_ATTRIBUTE_TOP,
+ GTK_CONSTRAINT_RELATION_EQ,
+ 0,
+ GTK_CONSTRAINT_STRENGTH_REQUIRED);
+ gtk_constraint_layout_add_constraint(layout, constraint);
- /* Actualisation du contenu du panneau */
+ constraint = gtk_constraint_new_constant(NULL,
+ GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
+ GTK_CONSTRAINT_RELATION_EQ,
+ min,
+ GTK_CONSTRAINT_STRENGTH_REQUIRED);
+ gtk_constraint_layout_add_constraint(layout, constraint);
- manager = get_project_manager();
+ /* Premier affichage */
- panel->sig_id = g_signal_connect(manager, "changed", G_CALLBACK(on_recent_list_changed), panel);
-
- g_welcome_panel_reload_project_list(panel, manager);
-
- g_welcome_panel_load_tips(panel);
-
- g_welcome_panel_check_version(panel);
+ gtk_label_set_markup(panel->hints, panel->raw_hints[panel->cur_hint]);
}
/******************************************************************************
* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -293,27 +214,24 @@ static void g_welcome_panel_init(GWelcomePanel *panel)
* *
******************************************************************************/
-static void g_welcome_panel_dispose(GWelcomePanel *panel)
+static void gtk_welcome_panel_dispose(GObject *object)
{
- GtkRecentManager *manager; /* Gestionnaire global */
+ GtkWelcomePanel *panel; /* Version spécialisée */
- if (panel->sig_id > 0)
- {
- manager = get_project_manager();
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_WELCOME_PANEL);
- g_signal_handler_disconnect(manager, panel->sig_id);
- panel->sig_id = 0;
+ panel = GTK_WELCOME_PANEL(object);
- }
+ g_clear_object(&panel->other_child);
- G_OBJECT_CLASS(g_welcome_panel_parent_class)->dispose(G_OBJECT(panel));
+ G_OBJECT_CLASS(gtk_welcome_panel_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : panel = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -323,133 +241,25 @@ static void g_welcome_panel_dispose(GWelcomePanel *panel)
* *
******************************************************************************/
-static void g_welcome_panel_finalize(GWelcomePanel *panel)
+static void gtk_welcome_panel_finalize(GObject *object)
{
- cairo_surface_destroy(panel->background);
+ GtkWelcomePanel *panel; /* Version spécialisée */
- free(panel->tips);
+ panel = GTK_WELCOME_PANEL(object);
- G_OBJECT_CLASS(g_welcome_panel_parent_class)->finalize(G_OBJECT(panel));
+ g_strfreev(panel->raw_hints);
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Fournit le nom interne attribué à l'élément réactif. *
-* *
-* Retour : Désignation (courte) de l'élément de l'éditeur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_welcome_panel_class_get_key(const GWelcomePanelClass *class)
-{
- char *result; /* Description à renvoyer */
-
- result = strdup(PANEL_WELCOME_ID);
-
- return result;
+ G_OBJECT_CLASS(gtk_welcome_panel_parent_class)->finalize(object);
}
/******************************************************************************
* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Fournit une indication sur la personnalité du panneau. *
+* Paramètres : box = liste GTK concernée par l'appel. *
+* panel = panneau d'accueil lié à la liste. *
* *
-* Retour : Identifiant lié à la nature unique du panneau. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PanelItemPersonality g_welcome_panel_class_get_personality(const GWelcomePanelClass *class)
-{
- PanelItemPersonality result; /* Personnalité à retourner */
-
- result = PIP_PERSISTENT_SINGLETON;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe à consulter. *
-* *
-* Description : Indique le chemin initial de la localisation d'un panneau. *
-* *
-* Retour : Chemin fixé associé à la position initiale. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_welcome_panel_class_get_path(const GWelcomePanelClass *class)
-{
- char *result; /* Emplacement à retourner */
-
- result = strdup("M");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un panneau d'accueil par défaut. *
-* *
-* Retour : Adresse de la structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPanelItem *g_welcome_panel_new(void)
-{
- GPanelItem *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_WELCOME_PANEL, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = composant à présenter à l'affichage. *
-* *
-* Description : Place un panneau dans l'ensemble affiché. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_welcome_panel_dock(GWelcomePanel *panel)
-{
- g_welcome_panel_set_user_origin(panel, true);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = panneau d'accueil à mettre à jour. *
-* *
-* Description : Charge l'ensemble des astuces. *
+* Description : Réagit à un changement de sélection de la liste de panneaux. *
* *
* Retour : - *
* *
@@ -457,414 +267,58 @@ static void g_welcome_panel_dock(GWelcomePanel *panel)
* *
******************************************************************************/
-static void g_welcome_panel_load_tips(GWelcomePanel *panel)
+static void gtk_welcome_panel_on_selected_rows_changed(GtkListBox *box, GtkWelcomePanel *panel)
{
- size_t i; /* Boucle de parcours */
-
- char *tips[] = {
-
- _("There is no need to install Chrysalide on your system if you only want to give it a try.\n\n"
- "Just compile the source code and run the program from there."),
-
- _("Chrysalide can be used in external Python scripts by setting PYTHONPATH to the directory "
- "containing the 'pychrysalide.so' file. For instance:\n\n"
- " cd plugins/pychrysa/.libs/\n"
- " export PYTHONPATH=$PWD\n\n"
- "Then run the interpreter suitable to your configuration (debug or release):\n\n"
- " python3-dbg -c 'import pychrysalide ; print(pychrysalide.mod_version())'"),
-
- _("All the configuration files for Chrysalide are located in $HOME/.config/chrysalide/."),
-
- _("The behavior of the main menu bar is copied from the one of a well known browser "
- "with a fox mascot.\n\n"
- "To make the menu bar appear and disappear, just press and release the Alt key.")
-
- };
-
- panel->count = ARRAY_SIZE(tips);
-
- panel->tips = (char **)calloc(panel->count, sizeof(char *));
-
- for (i = 0; i < panel->count; i++)
- panel->tips[i] = tips[i];
-
- shuffle(panel->tips, panel->count, sizeof(char *));
-
- panel->current = 0;
-
- g_welcome_panel_refresh_tip(panel);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant graphique à redessiner. *
-* cr = contexte graphique à utiliser. *
-* panel = panneau associé comportant des informations utiles. *
-* *
-* Description : Assure le dessin du fond de la bulle d'astuce. *
-* *
-* Retour : FALSE pour poursuivre la propagation de l'événement. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ GtkListBoxRow *row; /* Ligne sélectionnée */
+ GtkWidget *new; /* Nouvelles propriétés */
-static gboolean on_tip_background_draw(GtkWidget *widget, cairo_t *cr, GWelcomePanel *panel)
-{
- int wgt_width; /* Largeur disponible totale */
- int wgt_height; /* Hauteur disponible totale */
- int img_width; /* Largeur de l'image de fond */
- int img_height; /* Hauteur de l'image de fond */
- double scale; /* Echelle à appliquer */
+ row = gtk_list_box_get_selected_row(box);
- if (cairo_surface_status(panel->background) == CAIRO_STATUS_SUCCESS)
+ /**
+ * Perte de sélection : bascule sur les informations d'accueil.
+ */
+ if (row == NULL)
{
- wgt_width = gtk_widget_get_allocated_width(widget);
- wgt_height = gtk_widget_get_allocated_height(widget);
-
- img_width = cairo_image_surface_get_width(panel->background);
- img_height = cairo_image_surface_get_height(panel->background);
+ assert(panel->other_child != NULL);
- scale = wgt_height / (2.0 * img_height);
+ gtk_stack_set_visible_child(panel->properties, panel->def_child);
- cairo_scale(cr, scale, scale);
-
- cairo_set_source_surface(cr, panel->background,
- (wgt_width / scale) - img_width,
- ((wgt_height / scale) - img_height) / 2);
-
- cairo_paint(cr);
+ gtk_stack_remove(panel->properties, panel->other_child);
+ panel->other_child = NULL;
}
- return FALSE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton impliqué dans la procédure. *
-* panel = panneau associé comportant des informations utiles. *
-* *
-* Description : Réagit à la demande d'étude d'un nouveau binaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_new_binary_clicked(GtkButton *button, GWelcomePanel *panel)
-{
- GObject *ref; /* Espace de référencements */
- GtkMenuItem *item; /* Elément de menu simulé */
-
- ref = G_OBJECT(get_editor_window());
-
- item = GTK_MENU_ITEM(g_object_get_data(ref, "mnu_project_add_binary"));
-
- g_object_unref(ref);
-
- gtk_menu_item_activate(item);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : manager = gestion de fichiers récemment utilisés. *
-* panel = panneau associé comportant des informations utiles.*
-* *
-* Description : Actualise au besoin la liste des projets récents. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_recent_list_changed(GtkRecentManager *manager, GWelcomePanel *panel)
-{
- g_welcome_panel_reload_project_list(panel, manager);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = panneau comportant des informations utiles. *
-* manager = gestion de fichiers récemment utilisés. *
-* *
-* Description : Recharge une liste à jour des projets récents. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_welcome_panel_reload_project_list(GWelcomePanel *panel, GtkRecentManager *manager)
-{
- GtkBuilder *builder; /* Constructeur utilisé */
- GtkListStore *store; /* Modèle de gestion */
- bool empty; /* Liste vide ? */
- GList *recents; /* Liste des fichiers récents */
- GList *recent; /* Elément à traiter */
- GtkRecentInfo *info; /* Informations sur l'élément */
- GtkTreeIter iter; /* Point d'insertion */
-
- /* Réinitialisation */
-
- builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(G_PANEL_ITEM(panel)->widget));
-
- store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
-
- gtk_list_store_clear(store);
-
- empty = true;
-
- /* Chargement */
-
- recents = gtk_recent_manager_get_items(manager);
-
- if (recents != NULL)
- {
- for (recent = g_list_first(recents); recent != NULL; recent = g_list_next(recent))
- {
- info = recent->data;
-
- if (strcmp(gtk_recent_info_get_mime_type(info), "application/chrysalide.project") == 0)
- {
- gtk_list_store_append(store, &iter);
-
- gtk_list_store_set(store, &iter,
- RPC_VALID, true,
- RPC_FULLPATH, gtk_recent_info_get_uri_display(info),
- -1);
-
- empty = false;
-
- }
-
- gtk_recent_info_unref(info);
-
- }
-
- g_list_free(recents);
-
- }
-
- /* Indication par défaut */
- if (empty)
- {
- gtk_list_store_append(store, &iter);
-
- gtk_list_store_set(store, &iter,
- RPC_VALID, false,
- RPC_FULLPATH, _("<i>(No recent project)</i>"),
- -1);
-
- }
-
- g_object_unref(G_OBJECT(builder));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : treeview = liste graphique concernée par la procédure. *
-* path = chemin d'accès à la ligne sélectionnée. *
-* column = colonne concernée par la sélection. *
-* panel = panneau associé avec des informations utiles. *
-* *
-* Description : Réagit à une sélection décidée d'un projet particulier. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_row_activated_for_projects(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, GWelcomePanel *panel)
-{
- GtkTreeModel *model; /* Modèle de gestion */
- GtkTreeIter iter; /* Point de la consultation */
- gboolean valid; /* Validité de l'entrée */
- gchar *filename; /* Chemin d'accès au projet */
- GStudyProject *project; /* Nouveau projet à ouvrir */
-
- model = gtk_tree_view_get_model(treeview);
-
- if (gtk_tree_model_get_iter(model, &iter, path))
+ /**
+ * Bascule vers une nouvelle fenêtre.
+ */
+ else
{
- gtk_tree_model_get(model, &iter, RPC_VALID, &valid, RPC_FULLPATH, &filename, -1);
+ new = get_framework_panel_parameters(row);
+ assert(new != NULL);
- if (valid)
+ if (new != panel->other_child)
{
- project = g_study_project_open(filename, true);
-
- if (project != NULL)
- {
- set_current_project(project);
-
- push_project_into_recent_list(project);
-
- }
-
- g_free(filename);
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton de défilement des astuces activé; *
-* panel = panneau associé comportant des informations utiles. *
-* *
-* Description : Enregistre les conditions d'affichage du panneau d'accueil. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_startup_toggled(GtkToggleButton *button, GWelcomePanel *panel)
-{
- g_generic_config_set_value(get_main_configuration(),
- MPK_WELCOME_STARTUP, gtk_toggle_button_get_active(button));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = panneau d'accueil à mettre à jour. *
-* *
-* Description : Consulte les versions existantes et affiche une conclusion. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_welcome_panel_check_version(GWelcomePanel *panel)
-{
- bool skip; /* Saut de la vérification */
- bool unknown; /* Impossibilité de comparaison*/
- int current; /* Version courante */
- int sock; /* Canal de communication */
- bool status; /* Bilan d'une communication */
- char buffer[1024]; /* Tampon de réception */
- size_t got; /* Quantité de données reçues */
- char *version; /* Version récupérée */
- int available; /* Version disponible */
- GtkBuilder *builder; /* Constructeur utilisé */
- GtkLabel *label; /* Etiquette à éditer */
- char *msg; /* Message à faire paraître */
-
- g_generic_config_get_value(get_main_configuration(), MPK_WELCOME_CHECK, &skip);
- skip = !skip;
-
- unknown = true;
-
- current = atoi(VERSION);
-
- if (skip) goto check_process;
-
- /* Recherche en ligne */
+ gtk_stack_add_child(panel->properties, new);
+ gtk_stack_set_visible_child(panel->properties, new);
- sock = connect_via_tcp("www.chrysalide.re", "80", NULL);
- if (sock == -1) goto check_process;
+ if (panel->other_child != NULL)
+ gtk_stack_remove(panel->properties, panel->other_child);
-#define REQUEST "GET /version.last HTTP/1.1\r\nHost: www.chrysalide.re\r\n\r\n"
-
- status = safe_send(sock, REQUEST, strlen(REQUEST), 0);
- if (!status) goto check_done;
-
- status = recv_all(sock, buffer, sizeof(buffer), &got);
- if (!status) goto check_done;
-
- version = strstr(buffer, "\r\n\r\n");
-
- if (version != NULL)
- {
- available = atoi(version + 4);
-
- unknown = false;
-
- }
-
- check_done:
-
- close(sock);
-
- check_process:
-
- /* Affichage */
-
- builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(G_PANEL_ITEM(panel)->widget));
-
- label = GTK_LABEL(gtk_builder_get_object(builder, "version"));
-
- if (skip)
- asprintf(&msg,
- "Your version is: <b>%d</b>\n\n" \
- "Automatic version check is disabled.",
- current);
-
- else
- {
- if (unknown)
- asprintf(&msg,
- "Your version is: <b>%d</b>\n\n" \
- "Lastest available version is unknown.",
- current);
-
- else
- {
- if (current >= available)
- asprintf(&msg,
- "Your version is: <b>%d</b>\n\n" \
- "Lastest version is: <b>%d</b>\n\n" \
- "Your software is <span color='green'><b>up-to-date</b></span>.",
- current, available);
-
- else
- asprintf(&msg,
- "Your version is: <b>%d</b>\n\n" \
- "Lastest version is: <b>%d</b>\n\n" \
- "Your software is <span color='red'><b>outdated</b></span>.",
- current, available);
+ panel->other_child = new;
}
}
- gtk_label_set_markup(label, msg);
-
- free(msg);
-
- g_object_unref(G_OBJECT(builder));
-
}
/******************************************************************************
* *
-* Paramètres : button = bouton de défilement des astuces activé; *
-* panel = panneau associé comportant des informations utiles. *
+* Paramètres : button = bouton GTK concerné par l'appel. *
+* panel = panneau d'accueil lié à la liste. *
* *
-* Description : Affiche l'astuce précédente dans la liste globale. *
+* Description : Réagit à une demande d'affichage de l'astuce précédente. *
* *
* Retour : - *
* *
@@ -872,24 +326,24 @@ static void g_welcome_panel_check_version(GWelcomePanel *panel)
* *
******************************************************************************/
-static void on_tip_previous_clicked(GtkButton *button, GWelcomePanel *panel)
+static void gtk_welcome_panel_on_prev_hint_clicked(GtkButton *button, GtkWelcomePanel *panel)
{
- if (panel->current > 0)
- panel->current--;
+ if (panel->cur_hint > 0)
+ panel->cur_hint--;
else
- panel->current = panel->count - 1;
+ panel->cur_hint = panel->raw_count - 1;
- g_welcome_panel_refresh_tip(panel);
+ gtk_label_set_markup(panel->hints, panel->raw_hints[panel->cur_hint]);
}
/******************************************************************************
* *
-* Paramètres : button = bouton de défilement des astuces activé; *
-* panel = panneau associé comportant des informations utiles. *
+* Paramètres : button = bouton GTK concerné par l'appel. *
+* panel = panneau d'accueil lié à la liste. *
* *
-* Description : Affiche l'astuce suivante dans la liste globale. *
+* Description : Réagit à une demande d'affichage de l'astuce suivante. *
* *
* Retour : - *
* *
@@ -897,82 +351,27 @@ static void on_tip_previous_clicked(GtkButton *button, GWelcomePanel *panel)
* *
******************************************************************************/
-static void on_tip_next_clicked(GtkButton *button, GWelcomePanel *panel)
+static void gtk_welcome_panel_on_next_hint_clicked(GtkButton *button, GtkWelcomePanel *panel)
{
- if ((panel->current + 1) < panel->count)
- panel->current++;
+ if ((panel->cur_hint + 1) < panel->raw_count)
+ panel->cur_hint++;
else
- panel->current = 0;
+ panel->cur_hint = 0;
- g_welcome_panel_refresh_tip(panel);
+ gtk_label_set_markup(panel->hints, panel->raw_hints[panel->cur_hint]);
}
-/******************************************************************************
-* *
-* Paramètres : panel = panneau associé comportant des informations utiles. *
-* *
-* Description : Actualise l'affichage des astuces. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-static void g_welcome_panel_refresh_tip(GWelcomePanel *panel)
-{
- GtkBuilder *builder; /* Constructeur utilisé */
- GtkLabel *label; /* Etiquette de présentation */
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
- assert(panel->current < panel->count);
- builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(G_PANEL_ITEM(panel)->widget));
- label = GTK_LABEL(gtk_builder_get_object(builder, "tip"));
- gtk_label_set_markup(label, panel->tips[panel->current]);
- g_object_unref(G_OBJECT(builder));
-}
-/******************************************************************************
-* *
-* Paramètres : panel = panneau associé comportant des informations utiles. *
-* *
-* Description : Indique l'origine de l'affichage du panneau d'accueil. *
-* *
-* Retour : true si l'affichage est le fait de l'utilisateur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_welcome_panel_get_user_origin(const GWelcomePanel *panel)
-{
- return panel->uorigin;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : panel = panneau associé comportant des informations utiles.*
-* uorigin = true si l'affichage est le fait de l'utilisateur. *
-* *
-* Description : Détermine l'origine de l'affichage du panneau d'accueil. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_welcome_panel_set_user_origin(GWelcomePanel *panel, bool uorigin)
-{
- panel->uorigin = uorigin;
-
-}
diff --git a/src/gui/panels/welcome.h b/src/gui/panels/welcome.h
index 5cdd6a1..d9ea18d 100644
--- a/src/gui/panels/welcome.h
+++ b/src/gui/panels/welcome.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* welcome.h - prototypes pour le panneau d'accueil par défaut
*
- * Copyright (C) 2012-2019 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,42 +26,17 @@
#define _GUI_PANELS_WELCOME_H
-#include <i18n.h>
+#include <gtk/gtk.h>
-#include "../panel.h"
+#include "../../glibext/helpers.h"
+#include "../../gtkext/panel.h"
-#define PANEL_WELCOME_ID "welcome"
+#define GTK_TYPE_WELCOME_PANEL (gtk_welcome_panel_get_type())
-
-#define G_TYPE_WELCOME_PANEL g_welcome_panel_get_type()
-#define G_WELCOME_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_welcome_panel_get_type(), GWelcomePanel))
-#define G_IS_WELCOME_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_welcome_panel_get_type()))
-#define G_WELCOME_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WELCOME_PANEL, GWelcomePanelClass))
-#define G_IS_WELCOME_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WELCOME_PANEL))
-#define G_WELCOME_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WELCOME_PANEL, GWelcomePanelClass))
-
-
-/* Panneau d'accueil par défaut (instance) */
-typedef struct _GWelcomePanel GWelcomePanel;
-
-/* Panneau d'accueil par défaut (classe) */
-typedef struct _GWelcomePanelClass GWelcomePanelClass;
-
-
-/* Indique le type défini pour un panneau d'accueil. */
-GType g_welcome_panel_get_type(void);
-
-/* Crée un panneau d'accueil par défaut. */
-GPanelItem *g_welcome_panel_new(void);
-
-/* Indique l'origine de l'affichage du panneau d'accueil. */
-bool g_welcome_panel_get_user_origin(const GWelcomePanel *);
-
-/* Détermine l'origine de l'affichage du panneau d'accueil. */
-void g_welcome_panel_set_user_origin(GWelcomePanel *, bool);
+DECLARE_GTYPE(GtkWelcomePanel, gtk_welcome_panel, GTK, WELCOME_PANEL);
diff --git a/src/gui/panels/welcome.ui b/src/gui/panels/welcome.ui
index d016907..c545b1d 100644
--- a/src/gui/panels/welcome.ui
+++ b/src/gui/panels/welcome.ui
@@ -1,245 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
<interface>
- <requires lib="gtk+" version="3.12"/>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-new</property>
- <property name="icon_size">6</property>
- </object>
- <object class="GtkListStore" id="store">
- <columns>
- <!-- column-name valid -->
- <column type="gboolean"/>
- <!-- column-name fullpath -->
- <column type="gchararray"/>
- </columns>
- </object>
- <object class="GtkOffscreenWindow" id="offscreenwindow1">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkBox" id="box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="homogeneous">True</property>
- <child>
- <object class="GtkBox" id="box2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="orientation">vertical</property>
- <property name="spacing">8</property>
- <child>
- <object class="GtkAlignment" id="alignment1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="top_padding">180</property>
- <property name="bottom_padding">30</property>
- <child>
- <object class="GtkButton" id="button1">
- <property name="label" translatable="yes">New binary...</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">image1</property>
- <property name="image_position">top</property>
- <property name="always_show_image">True</property>
- <signal name="clicked" handler="on_new_binary_clicked" swapped="no"/>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Last projects:</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkTreeView" id="treeview">
- <property name="height_request">250</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="margin_left">8</property>
- <property name="hexpand">True</property>
- <property name="model">store</property>
- <property name="headers_visible">False</property>
- <property name="rules_hint">True</property>
- <signal name="row-activated" handler="on_row_activated_for_projects" swapped="no"/>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection1"/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="startup">
- <property name="label" translatable="yes">Show this panel at startup.</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="valign">end</property>
- <property name="vexpand">True</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_startup_toggled" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
+
+ <template class="GtkWelcomePanel" parent="GtkTiledPanel">
<child>
- <object class="GtkBox" id="box3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
- <property name="orientation">vertical</property>
- <property name="spacing">8</property>
- <child>
- <object class="GtkBox" id="box4">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="homogeneous">True</property>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">automatic</property>
+ <property name="vscrollbar-policy">automatic</property>
+ <property name="hexpand">TRUE</property>
+ <property name="vexpand">TRUE</property>
+ <property name="has-frame">0</property>
<child>
- <object class="GtkLabel" id="version">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="opacity">0.81999999977648264</property>
- <property name="use_markup">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="opacity">0.81999999999999995</property>
- <property name="label" translatable="yes">Get access to the online documentation and stay tuned by visiting the official website : &lt;a href="http://chrysalide.re"&gt;chrysalide.re&lt;/a&gt;
-
-You can also follow Chrysalide on Twitter : &lt;a href="http://twitter.com/chrysalide_ref"&gt;@chrysalide_ref&lt;/a&gt;</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="track_visited_links">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="tip">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="yalign">1</property>
- <property name="xpad">8</property>
- <property name="ypad">8</property>
- <property name="label" translatable="yes">label</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- <signal name="draw" handler="on_tip_background_draw" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButtonBox" id="buttonbox1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">8</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="button3">
- <property name="label" translatable="yes">Previous</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <signal name="clicked" handler="on_tip_previous_clicked" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button2">
- <property name="label" translatable="yes">Next</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <signal name="clicked" handler="on_tip_next_clicked" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
+ <object class="GtkGrid">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="column-spacing">64</property>
+ <property name="column-homogeneous">TRUE</property>
+ <property name="margin-bottom">32</property>
+ <property name="margin-end">32</property>
+ <property name="margin-start">32</property>
+ <property name="margin-top">32</property>
+
+ <!-- Launcher list -->
+ <child>
+ <object class="GtkListBox" id="list">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="selection-mode">GTK_SELECTION_SINGLE</property>
+ <property name="activate-on-single-click">0</property>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+
+ <style>
+ <class name="boxed-list"/>
+ <class name="frame"/>
+ </style>
+
+ <signal name="selected-rows-changed" handler="gtk_welcome_panel_on_selected_rows_changed"/>
+
+ </object>
+ </child>
+
+ <!-- Hints / options -->
+ <child>
+ <object class="GtkStack" id="properties">
+ <property name="halign">start</property>
+ <property name="valign">fill</property>
+
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+
+ <child>
+
+ <object class="GtkStackPage">
+ <property name="name">default</property>
+ <property name="title">Welcome</property>
+
+ <property name="child">
+ <object class="GtkGrid" id="def_child">
+ <property name="halign">start</property>
+ <property name="valign">fill</property>
+ <property name="column-spacing">16</property>
+ <property name="column-homogeneous">FALSE</property>
+
+ <!-- Text -->
+
+ <child>
+ <object class="GtkLabel" id="hints">
+ <property name="halign">start</property>
+ <property name="valign">fill</property>
+ <property name="xalign">0</property>
+ <property name="yalign">1</property>
+ <property name="vexpand">1</property>
+ <property name="width-request">50</property>
+ <property name="wrap">TRUE</property>
+
+ <property name="layout-manager">
+ <object class="GtkConstraintLayout">
+ <!--
+ <constraints>
+
+ <constraint target="super" target-attribute="left"
+ relation="eq"
+ constant="0"
+ strength="required"/>
+
+ <constraint target="super" target-attribute="top"
+ relation="eq"
+ constant="0"
+ strength="required"/>
+
+ <constraint target="super" target-attribute="right"
+ relation="eq"
+ constant="340"
+ strength="required"/>
+
+ </constraints>
+ -->
+ </object>
+ </property>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+
+ </object>
+ </child>
+
+ <!-- Prev/Next buttons -->
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="homogeneous">TRUE</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="halign">end</property>
+ <signal name="clicked" handler="gtk_welcome_panel_on_prev_hint_clicked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="halign">start</property>
+ <signal name="clicked" handler="gtk_welcome_panel_on_next_hint_clicked"/>
+ </object>
+ </child>
+
+ <style>
+ <class name="linked"/>
+ </style>
+
+ </object>
+ </child>
+
+ <style>
+ <class name="hints"/>
+ </style>
+
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
</child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
+ </object>
</child>
- </object>
- </child>
- </object>
+ </template>
+
</interface>
diff --git a/src/gui/style.css b/src/gui/style.css
new file mode 100644
index 0000000..dce41fa
--- /dev/null
+++ b/src/gui/style.css
@@ -0,0 +1,71 @@
+
+/* Extension de style */
+
+.dim-label {
+
+ margin-bottom: 4px;
+
+}
+
+
+.boxed-widget {
+
+ border-top-left-radius: 12px;
+ border-top-right-radius: 12px;
+
+ border-bottom-left-radius: 12px;
+ border-bottom-right-radius: 12px;
+
+}
+
+
+list.boxed-list, list.boxed-list > row:first-child {
+
+ border-top-left-radius: 12px;
+ border-top-right-radius: 12px;
+
+}
+
+list.boxed-list, list.boxed-list > row:last-child {
+
+ border-bottom-left-radius: 12px;
+ border-bottom-right-radius: 12px;
+
+}
+
+
+/* about.css */
+
+@import url('resource:///re/chrysalide/framework/gui/dialogs/about.css');
+
+
+/* welcome.css */
+
+grid.hints {
+
+ background-image: -gtk-icontheme('tipoftheday-symbolic');
+ background-position: right top;
+ background-size: 200px auto;
+ background-repeat: no-repeat;
+
+ min-height: 250px;
+
+}
+
+grid.hints > box {
+
+ min-width: 130px;
+
+}
+
+
+/* dockstation.css */
+
+.control-button {
+
+ min-height: 0;
+ min-width: 0;
+
+ padding: 6px;
+
+}
diff --git a/src/gui/window-int.h b/src/gui/window-int.h
new file mode 100644
index 0000000..4f3dd57
--- /dev/null
+++ b/src/gui/window-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * window.h - prototypes internes pour la construction d'une fenêtre graphique principale
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_WINDOW_INT_H
+#define _GUI_WINDOW_INT_H
+
+
+#include "window.h"
+#include "../gtkext/grid.h"
+
+
+
+/* Définition de l'application principale graphique (instance) */
+struct _GtkFrameworkWindow
+{
+ GtkApplicationWindow parent; /* A laisser en premier */
+
+ GSettings *settings; /* Paramètres globaux */
+
+ GtkTilingGrid *grid; /* Réceptacle de panneaux */
+ GtkStatusStack *status; /* Barre de statut */
+
+ GtkTiledPanel *main; /* Panneau principal courant */
+
+};
+
+/* Définition de l'application principale graphique (classe) */
+struct _GtkFrameworkWindowClass
+{
+ GtkApplicationWindowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une fenêtre principale pour Chrysalide. */
+bool gtk_framework_window_create(GtkFrameworkWindow *, GtkApplication *);
+
+
+
+#endif /* _GUI_WINDOW_INT_H */
diff --git a/src/gui/window.c b/src/gui/window.c
new file mode 100644
index 0000000..e14ecf7
--- /dev/null
+++ b/src/gui/window.c
@@ -0,0 +1,621 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * window.c - construction d'une fenêtre graphique principale
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 "window.h"
+
+
+#include "window-int.h"
+#include "core/panels.h"
+#include "dialogs/about.h"
+#include "dialogs/preferences.h"
+#include "panels/logs.h"
+#include "panels/welcome.h"
+#include "../gtkext/grid.h"
+#include "../gtkext/helpers.h"
+
+
+
+/* Initialise la classe des applications majeures de Chrysalide. */
+static void gtk_framework_window_class_init(GtkFrameworkWindowClass *);
+
+/* Initialise une application principale pour Chrysalide. */
+static void gtk_framework_window_init(GtkFrameworkWindow *);
+
+/* Supprime toutes les références externes. */
+static void gtk_framework_window_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_framework_window_finalize(GObject *);
+
+/* Bascule l'affichage d'un panneau de bordure. */
+static void gtk_framework_window_toggle_pannel_visibility(GtkFrameworkWindow *, TilingGridBorder);
+
+/* Réagit à une activation de bascule du panneau supérieur. */
+static void gtk_framework_window_activate_toggle_top(GSimpleAction *, GVariant *, gpointer);
+
+/* Réagit à une activation de bascule du panneau de gauche. */
+static void gtk_framework_window_activate_toggle_left(GSimpleAction *action, GVariant *, gpointer);
+
+/* Réagit à une activation de bascule du panneau de droite. */
+static void gtk_framework_window_activate_toggle_right(GSimpleAction *, GVariant *, gpointer);
+
+/* Réagit à une activation de bascule du panneau inférieur. */
+static void gtk_framework_window_activate_toggle_bottom(GSimpleAction *, GVariant *, gpointer);
+
+/* Réagit à une activation du menu "Préférences" de la fenetre. */
+static void gtk_framework_window_activate_preferences(GSimpleAction *, GVariant *, gpointer);
+
+/* Réagit à une activation du menu "A propos de" de la fenetre. */
+static void gtk_framework_window_activate_about(GSimpleAction *, GVariant *, gpointer);
+
+
+
+/* Indique le type défini pour une fenêtre graphique principale de Chrysalide. */
+G_DEFINE_TYPE(GtkFrameworkWindow, gtk_framework_window, GTK_TYPE_APPLICATION_WINDOW);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des applications majeures de Chrysalide.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_framework_window_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_framework_window_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ g_type_ensure(GTK_TYPE_TILING_GRID);
+ g_type_ensure(GTK_TYPE_STATUS_STACK);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/window.ui");
+
+ gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, grid);
+ gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, status);
+
+ /* Active une action native (cf. https://docs.gtk.org/gtk4/class.Window.html#actions) */
+ gtk_widget_class_add_binding_action(widget, GDK_KEY_Q, GDK_CONTROL_MASK, "window.close", NULL);
+
+ gtk_widget_class_add_binding_action(widget, GDK_KEY_comma, GDK_CONTROL_MASK, "win.preferences", NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : window = instance à initialiser. *
+* *
+* Description : Initialise une application principale pour Chrysalide. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_init(GtkFrameworkWindow *window)
+{
+ GAction *action; /* Action mise en place */
+
+ static GActionEntry app_entries[] = {
+ { "toggle-top", gtk_framework_window_activate_toggle_top, NULL, NULL, NULL },
+ { "toggle-left", gtk_framework_window_activate_toggle_left, NULL, NULL, NULL },
+ { "toggle-right", gtk_framework_window_activate_toggle_right, NULL, NULL, NULL },
+ { "toggle-bottom", gtk_framework_window_activate_toggle_bottom, NULL, NULL, NULL },
+ { "preferences", gtk_framework_window_activate_preferences, NULL, NULL, NULL },
+ { "about", gtk_framework_window_activate_about, NULL, NULL, NULL },
+ };
+
+ gtk_widget_init_template(GTK_WIDGET(window));
+
+ window->settings = g_settings_new(FRAMEWORK_WINDOW_ID);
+
+ g_settings_bind(window->settings, "window-width", G_OBJECT(window), "default-width", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind(window->settings, "window-height", G_OBJECT(window), "default-height", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind(window->settings, "window-maximized", G_OBJECT(window), "maximized", G_SETTINGS_BIND_DEFAULT);
+
+ window->main = NULL;
+
+ g_action_map_add_action_entries(G_ACTION_MAP(window),
+ app_entries, G_N_ELEMENTS(app_entries),
+ window);
+
+ /**
+ * Définition de l'accès aux actions pour obtenir un effet de bord sur
+ * l'accès aux boutons graphiques de déclenchement.
+ */
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-top");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-top",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-left");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-left",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-right");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-right",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-bottom");
+
+ g_object_bind_property(G_OBJECT(window->grid), "empty-bottom",
+ G_OBJECT(action), "enabled",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_dispose(GObject *object)
+{
+ GtkFrameworkWindow *window; /* Version spécialisée */
+
+ window = GTK_FRAMEWORK_WINDOW(object);
+
+ gtk_widget_dispose_template(GTK_WIDGET(window), GTK_TYPE_FRAMEWORK_WINDOW);
+
+ g_clear_object(&window->settings);
+
+ g_clear_object(&window->main);
+
+ G_OBJECT_CLASS(gtk_framework_window_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_framework_window_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : app = application GTK de rattachement. *
+* *
+* Description : Crée une nouvelle application principale pour Chrysalide. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkApplicationWindow *gtk_framework_window_new(GtkApplication *app)
+{
+ GtkApplicationWindow *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_FRAMEWORK_WINDOW, NULL);
+
+ if (!gtk_framework_window_create(GTK_FRAMEWORK_WINDOW(result), app))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : window = instance de fenêtre principale à remplir. *
+* app = application GTK de rattachement. *
+* *
+* Description : Met en place une fenêtre principale pour Chrysalide. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_framework_window_create(GtkFrameworkWindow *window, GtkApplication *app)
+{
+ bool result; /* Bilan à retourner */
+ GtkTiledPanel *panel; /* Panneau d'affichage */
+ GtkCssProvider *css; /* Feuille de style maison */
+
+ result = true;
+
+ gtk_window_set_application(GTK_WINDOW(window), app);
+
+ /* Inclusion d'un écran d'accueil */
+
+ panel = get_framework_panel_singleton(GTK_TYPE_WELCOME_PANEL);
+
+ gtk_framework_window_add(window, panel);
+
+ if (1/* FIXME : first time */)
+ {
+ panel = get_framework_panel_singleton(GTK_TYPE_LOGS_PANEL);
+
+ gtk_framework_window_add(window, panel);
+
+ }
+
+ /* Chargement des extensions de thème */
+
+ css = gtk_css_provider_new();
+
+ gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gtkext/hexview.css");
+
+ gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)),
+ GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ unref_object(css);
+
+ css = gtk_css_provider_new();
+
+ gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gui/style.css");
+
+ gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)),
+ GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ unref_object(css);
+
+ /* Fin des chargements */
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : window = instance de fenêtre principale à manipuler. *
+* border = sélection de la zone à considérer. *
+* *
+* Description : Bascule l'affichage d'un panneau de bordure. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_toggle_pannel_visibility(GtkFrameworkWindow *window, TilingGridBorder border)
+{
+ bool state; /* Etat courant à basculer */
+
+ state = gtk_tiling_grid_get_visible(window->grid, border);
+
+ state = !state;
+
+ gtk_tiling_grid_set_visible(window->grid, border, state);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau supérieur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_top(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_TOP);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau de gauche. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_left(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_LEFT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau de droite. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_right(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_RIGHT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation de bascule du panneau inférieur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_toggle_bottom(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ gtk_framework_window_toggle_pannel_visibility(_window, TGB_BOTTOM);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation du menu "Préférences" de la fenetre. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_preferences(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ GtkFrameworkWindow *window; /* Fenêtre principale associée */
+ GtkWindow *dialog; /* Boîte de dialogue à afficher*/
+
+ window = _window;
+
+ dialog = gtk_preferences_dialog_new(GTK_WINDOW(window));
+
+ gtk_window_present(dialog);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : action = désignation de l'action concernée par l'appel. *
+* unused = adresse non utilisée ici. *
+* _window = instance de fenêtre principale à manipuler. *
+* *
+* Description : Réagit à une activation du menu "A propos de" de la fenetre. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_framework_window_activate_about(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+ GtkFrameworkWindow *window; /* Fenêtre principale associée */
+ GtkWindow *dialog; /* Boîte de dialogue à afficher*/
+
+ window = _window;
+
+ dialog = gtk_app_about_dialog_new(GTK_WINDOW(window));
+
+ gtk_window_present(dialog);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : window = instance de fenêtre principale à consulter. *
+* *
+* Description : Fournit une référence à la barre de statut intégrée. *
+* *
+* Retour : Composant GTK en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkStatusStack *gtk_framework_window_get_status_stack(const GtkFrameworkWindow *window)
+{
+ GtkStatusStack *result; /* Instance à retourner */
+
+ result = window->status;
+ ref_object(result);
+
+ return result;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : window = instance de fenêtre principale à remplir. *
+* panel = nouveau panneau à afficher. *
+* *
+* Description : Ajoute un panneau à la fenêtre principale de Chrysalide. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_framework_window_add(GtkFrameworkWindow *window, /* __steal */GtkTiledPanel *panel)
+{
+ GtkWidget *bar; /* Barre de titre */
+ GListStore *list; /* Liste éventuelle à intégrer */
+ guint count; /* Nombre d'élements présents */
+ guint i; /* Boucle de parcours */
+ GtkWidget *widget; /* Composant à intégrer */
+ FrameworkPanelPersonality personality; /* Propriétés du panneau */
+
+
+
+ gtk_tiling_grid_add_panel(window->grid, panel, G_OBJECT_TYPE(panel) == GTK_TYPE_WELCOME_PANEL);
+
+
+
+
+ bar = gtk_window_get_titlebar(GTK_WINDOW(window));
+
+ if (bar == NULL) ////////// REMME
+ {
+ bar = gtk_header_bar_new();
+ gtk_window_set_titlebar(GTK_WINDOW(window), bar);
+ } /////////////////////////////
+
+ list = gtk_tiled_panel_get_title_widgets(panel, false);
+
+ if (list != NULL)
+ {
+ count = g_list_model_get_n_items(G_LIST_MODEL(list));
+
+ for (i = 0; i < count; i++)
+ {
+ widget = GTK_WIDGET(g_list_model_get_item(G_LIST_MODEL(list), i));
+ gtk_header_bar_pack_end(GTK_HEADER_BAR(bar), widget);
+ }
+
+ unref_object(list);
+
+ }
+
+ /* Mise à jour des liens vers un panneau principal */
+
+ personality = get_framework_panel_personality(G_OBJECT_TYPE(panel));
+
+ if (personality & FPP_MAIN_PANEL)
+ gtk_framework_window_notify_new_main_panel_state(window, panel, true);
+
+ else
+ {
+ if (window->main != NULL)
+ gtk_tiled_panel_notify_new_main_panel_state(panel, window->main, true);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : window = instance de fenêtre principale à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_framework_window_notify_new_main_panel_state(GtkFrameworkWindow *window, GtkTiledPanel *main, bool activated)
+{
+ if (activated)
+ {
+ g_clear_object(&window->main);
+
+ window->main = main;
+ ref_object(main);
+
+ }
+
+ else
+ {
+ if (main == window->main)
+ g_clear_object(&window->main);
+
+ }
+
+ gtk_tiling_grid_notify_new_main_panel_state(window->grid, main, activated);
+
+}
diff --git a/src/gui/window.h b/src/gui/window.h
new file mode 100644
index 0000000..077d51a
--- /dev/null
+++ b/src/gui/window.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * window.h - prototypes pour la construction d'une fenêtre graphique principale
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_WINDOW_H
+#define _GUI_WINDOW_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+#include "../gtkext/panel.h"
+#include "../gtkext/statusstack.h"
+
+
+
+/* Définition d'un identifiant unique */
+#define FRAMEWORK_WINDOW_ID "re.chrysalide.framework.gui"
+
+
+
+#define GTK_TYPE_FRAMEWORK_WINDOW (gtk_framework_window_get_type())
+
+DECLARE_GTYPE(GtkFrameworkWindow, gtk_framework_window, GTK, FRAMEWORK_WINDOW);
+
+
+/* Crée une nouvelle application principale pour Chrysalide. */
+GtkApplicationWindow *gtk_framework_window_new(GtkApplication *);
+
+/* Fournit une référence à la barre de statut intégrée. */
+GtkStatusStack *gtk_framework_window_get_status_stack(const GtkFrameworkWindow *);
+
+/* Ajoute un panneau à la fenêtre principale de Chrysalide. */
+void gtk_framework_window_add(GtkFrameworkWindow *, GtkTiledPanel *);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_framework_window_notify_new_main_panel_state(GtkFrameworkWindow *, GtkTiledPanel *, bool);
+
+
+
+#endif /* _GUI_WINDOW_H */
diff --git a/src/gui/window.ui b/src/gui/window.ui
new file mode 100644
index 0000000..1c6a89a
--- /dev/null
+++ b/src/gui/window.ui
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+
+ <menu id="main_menu_model">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Preferences</attribute>
+ <attribute name="action">win.preferences</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">About</attribute>
+ <attribute name="action">win.about</attribute>
+ </item>
+ </section>
+ </menu>
+
+ <template class="GtkFrameworkWindow" parent="GtkApplicationWindow">
+ <property name="title" translatable="no">Chrysalide</property>
+ <property name="default-width">800</property>
+ <property name="default-height">600</property>
+ <property name="icon-name">chrysalide-logo</property>
+
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+
+ <child type="start">
+ <object class="GtkToggleButton">
+ <property name="icon-name">dock-station-left-symbolic</property>
+ <property name="action-name">win.toggle-left</property>
+ <property name="active" bind-source="grid" bind-property="visible-left" bind-flags="sync-create"/>
+ </object>
+ </child>
+
+ <child type="end">
+ <object class="GtkToggleButton">
+ <property name="icon-name">dock-station-right-symbolic</property>
+ <property name="action-name">win.toggle-right</property>
+ <property name="active" bind-source="grid" bind-property="visible-right" bind-flags="sync-create"/>
+ </object>
+ </child>
+
+ <child type="end">
+ <object class="GtkMenuButton">
+ <property name="icon-name">open-menu-symbolic</property>
+ <property name="menu-model">main_menu_model</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkTilingGrid" id="grid">
+ <property name="vexpand">TRUE</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">horizontal</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStatusStack" id="status">
+ <property name="show-bottom" bind-source="grid" bind-property="visible-bottom" bind-flags="sync-create"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+
+</interface>
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index dd191fa..fa65484 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,13 +1,18 @@
noinst_LTLIBRARIES = libplugins.la
-libplugins_la_SOURCES = \
- dt.h dt.c \
- pglist.h pglist.c \
- plugin-def.h \
- plugin-int.h \
- plugin.h plugin.c \
- self.h
+libplugins_la_SOURCES = \
+ manager-int.h \
+ manager.h manager.c \
+ native-int.h \
+ native.h native.c \
+ pglist.h pglist.c \
+ plugin-def.h \
+ plugin-int.h \
+ plugin.h plugin.c \
+ self.h \
+ tweakable-int.h \
+ tweakable.h tweakable.c
libplugins_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/plugins/dt.c b/src/plugins/dt.c
deleted file mode 100644
index 28b70bb..0000000
--- a/src/plugins/dt.c
+++ /dev/null
@@ -1,545 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * dt.c - possibilité de créer de nouveaux types de façon dynamique
- *
- * Copyright (C) 2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "dt.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include "pglist.h"
-
-
-
-/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */
-
-
-#define G_TYPE_DYNAMIC_TYPES g_dynamic_types_get_type()
-#define G_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes))
-#define G_IS_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES))
-#define G_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
-#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES))
-#define G_DYNAMIC_TYPES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
-
-
-/* Mémorisation des caractéristiques de type */
-typedef struct _type_dyn_info_t
-{
- GType type; /* Identifiant unique obtenu */
-
- GClassInitFunc cinit; /* Phase d'initialisation #1 */
- gconstpointer data; /* Eventuelles données utiles */
-
- GInstanceInitFunc init; /* Phase d'initialisation #2 */
-
-} type_dyn_info_t;
-
-/* Description de fichier binaire (instance) */
-typedef struct _GDynamicTypes
-{
- GObject parent; /* A laisser en premier */
-
- type_dyn_info_t **info; /* Liste d'informations utiles */
- size_t count; /* Taille de cette liste */
-
-} GDynamicTypes;
-
-/* Description de fichier binaire (classe) */
-typedef struct _GDynamicTypesClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-} GDynamicTypesClass;
-
-
-/* Indique le type défini pour une gestion de types dynamique. */
-static GType g_dynamic_types_get_type(void);
-
-/* Initialise la classe de gestion de types dynamique. */
-static void g_dynamic_types_class_init(GDynamicTypesClass *);
-
-/* Initialise une gestion de types dynamique. */
-static void g_dynamic_types_init(GDynamicTypes *);
-
-/* Procède à l'initialisation de l'interface de typage nouveau. */
-static void g_dynamic_types_interface_init(GTypePluginClass *);
-
-/* Supprime toutes les références externes. */
-static void g_dynamic_types_dispose(GDynamicTypes *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_dynamic_types_finalize(GDynamicTypes *);
-
-/* Crée un nouveau gestionnaire de nouveaux types. */
-static GDynamicTypes *g_dynamic_types_new(void);
-
-/* Marque une augmentation des utilisations. */
-static void g_dynamic_types_use(GDynamicTypes *);
-
-/* Marque une diminution des utilisations. */
-static void g_dynamic_types_unuse(GDynamicTypes *);
-
-/* Complète la définition d'un type dynamiquement. */
-static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *);
-
-/* Retrouve les informations concernant un type dynamique. */
-static type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *, GType);
-
-/* Fournit un identifiant GLib pour un nouveau type. */
-static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc, gconstpointer, GInstanceInitFunc);
-
-
-
-/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-
-
-/* Encadrement des nouveaux types dérivés */
-static GDynamicTypes *_chrysalide_dtypes = NULL;
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* MODULE DE GESTION DES NOUVEAUX */
-/* ---------------------------------------------------------------------------------- */
-
-/* Indique le type défini pour une gestion de types dynamique. */
-G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init));
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe de gestion de types dynamique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_class_init(GDynamicTypesClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose;
- object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = instance à initialiser. *
-* *
-* Description : Initialise une gestion de types dynamique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_init(GDynamicTypes *types)
-{
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : iface = interface GLib à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'interface de typage nouveau. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_interface_init(GTypePluginClass *iface)
-{
- iface->use_plugin = (GTypePluginUse)g_dynamic_types_use;
- iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse;
- iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type;
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : types = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_dispose(GDynamicTypes *types)
-{
- size_t i; /* Boucle de parcours */
- type_dyn_info_t *info; /* Information à exploiter */
- gpointer g_class; /* Classe à oublier */
-
- for (i = 0; i < types->count; i++)
- {
- info = types->info[i];
-
- if (info->type != G_TYPE_INVALID)
- {
- g_class = g_type_class_peek(info->type);
- g_type_class_unref(g_class);
-
- info->type = G_TYPE_INVALID;
-
- }
-
- }
-
- G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_finalize(GDynamicTypes *types)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < types->count; i++)
- free(types->info[i]);
-
- if (types->info != NULL)
- free(types->info);
-
- G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un nouveau gestionnaire de nouveaux types. *
-* *
-* Retour : Instance mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GDynamicTypes *g_dynamic_types_new(void)
-{
- GDynamicTypes *result; /* Adresse à retourner */
-
- result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = gestionnaire de types courant. *
-* *
-* Description : Marque une augmentation des utilisations. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_use(GDynamicTypes *types)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = gestionnaire de types courant. *
-* *
-* Description : Marque une diminution des utilisations. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_unuse(GDynamicTypes *types)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = gestionnaire de types courant. *
-* type = nouveau type GLib à traiter. *
-* info = information concernant ce type à constituer. [OUT] *
-* table = table de valeur à éventuellement initialiser. [OUT] *
-* *
-* Description : Complète la définition d'un type dynamiquement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table)
-{
- type_dyn_info_t *nfo; /* Source d'inspiration */
- GType parent; /* Type parent du type */
- GTypeQuery query; /* Informations complémentaires*/
-
- /* Consultation */
-
- nfo = g_dynamic_types_find(types, type);
- assert(nfo != NULL);
-
- parent = g_type_parent(type);
- g_type_query(parent, &query);
-
- /* Définition */
-
- info->class_size = query.class_size;
- info->class_init = nfo->cinit;
- info->class_data = nfo->data;
-
- info->instance_size = query.instance_size;
- info->instance_init = nfo->init;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = type GLib parent. *
-* type = identifiant du type GLib à considérer. *
-* *
-* Description : Retrouve les informations concernant un type dynamique. *
-* *
-* Retour : Structure contenant les informations associées au type. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, GType target)
-{
- type_dyn_info_t *result; /* Informations à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < types->count && result == NULL; i++)
- if (types->info[i]->type == target)
- result = types->info[i];
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = type GLib parent. *
-* name = désignation du nouveau type. *
-* cinit = procédure d'initialisation de la classe associée. *
-* data = éventuelles données à associer à la future classe. *
-* init = procédure d'initialisation pour chaque instance. *
-* *
-* Description : Fournit un identifiant GLib pour un nouveau type. *
-* *
-* Retour : identifiant d'un nouveau type valide, ou G_TYPE_INVALID. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc cinit, gconstpointer data, GInstanceInitFunc init)
-{
- GType result; /* Identifiant à retourner */
- type_dyn_info_t *new; /* Mémorisation de paramètres */
-
- /* Création d'un nouveau type adapté */
-
- result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0);
-
- if (result == G_TYPE_INVALID)
- goto exit;
-
- new = malloc(sizeof(type_dyn_info_t));
-
- new->type = result;
-
- new->cinit = cinit;
- new->data = data;
-
- new->init = init;
-
- /* Inscription définitive */
-
- types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *));
-
- types->info[types->count - 1] = new;
-
- exit:
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* ACCOMPAGNEMENTS DES NOUVEAUX TYPES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Lance le support de dérivations de types dans Chrysalide. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool init_chrysalide_dynamic_types(void)
-{
- bool result; /* Bilan à retourner */
-
- _chrysalide_dtypes = g_dynamic_types_new();
-
- result = (_chrysalide_dtypes != NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Arrête le support de dérivations de types dans Chrysalide. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void exit_chrysalide_dynamic_types(void)
-{
- g_object_unref(G_OBJECT(_chrysalide_dtypes));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = type GLib parent. *
-* name = désignation du nouveau type. *
-* cinit = procédure d'initialisation de la classe associée. *
-* data = éventuelles données à associer à la future classe. *
-* init = procédure d'initialisation pour chaque instance. *
-* *
-* Description : Fournit un identifiant GLib pour un nouveau type. *
-* *
-* Retour : Identifiant d'un nouveau type valide, ou G_TYPE_INVALID. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GType build_dynamic_type(GType parent, const char *name, GClassInitFunc cinit, gconstpointer data, GInstanceInitFunc init)
-{
- GType result; /* Identifiant à retourner */
-
- result = g_type_from_name(name);
-
- if (result == 0)
- result = g_dynamic_types_register_type(_chrysalide_dtypes, parent, name, cinit, data, init);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type d'instance à créer. *
-* *
-* Description : Crée un objet à partir d'un type, dynamique ou classique. *
-* *
-* Retour : Instance d'objet mise en place ou NULL en cas d'erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gpointer create_object_from_type(GType type)
-{
- GObject *result; /* Instance à retourner */
-
- result = NULL;
-
- if (g_dynamic_types_find(_chrysalide_dtypes, type) != NULL)
- result = build_type_instance(type);
-
- else
- result = g_object_new(type, NULL);
-
- assert(result != NULL);
-
- return result;
-
-}
diff --git a/src/plugins/dt.h b/src/plugins/dt.h
deleted file mode 100644
index 5c92593..0000000
--- a/src/plugins/dt.h
+++ /dev/null
@@ -1,50 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique
- *
- * Copyright (C) 2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _PLUGINS_DT_H
-#define _PLUGINS_DT_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-
-/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-
-
-/* Lance le support de dérivations de types dans Chrysalide. */
-bool init_chrysalide_dynamic_types(void);
-
-/* Arrête le support de dérivations de types dans Chrysalide. */
-void exit_chrysalide_dynamic_types(void);
-
-/* Fournit un identifiant GLib pour un nouveau type. */
-GType build_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer, GInstanceInitFunc);
-
-/* Crée un objet à partir d'un type, dynamique ou classique. */
-gpointer create_object_from_type(GType);
-
-
-
-#endif /* _PLUGINS_PYCHRYSALIDE_DT_H */
diff --git a/src/plugins/manager-int.h b/src/plugins/manager-int.h
new file mode 100644
index 0000000..dbd1d69
--- /dev/null
+++ b/src/plugins/manager-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager-int.h - définitions internes propres aux interventions dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_MANAGER_INT_H
+#define _PLUGINS_MANAGER_INT_H
+
+
+#include "manager.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Accompagne la fin du chargement des modules natifs. */
+typedef void (* handle_native_plugins_cb) (GPluginManager *);
+
+/* Prend acte du chargement de l'ensemble des greffons. */
+typedef void (* handle_all_plugins_cb) (GPluginManager *);
+
+
+/* Accompagnant dans la gestion des extensions (interface) */
+struct _GPluginManagerInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ handle_native_plugins_cb handle_native; /* Greffons natifs chargés */
+ handle_all_plugins_cb handle_all; /* Ensemble des greffons chargé*/
+
+};
+
+
+
+#endif /* _PLUGINS_MANAGER_INT_H */
diff --git a/src/plugins/manager.c b/src/plugins/manager.c
new file mode 100644
index 0000000..381fbc1
--- /dev/null
+++ b/src/plugins/manager.c
@@ -0,0 +1,113 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.c - intervention dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "manager.h"
+
+
+#include "manager-int.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Procède à l'initialisation de l'interface de gestion. */
+static void g_plugin_manager_default_init(GPluginManagerInterface *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERVENTION DANS LA GESTION DE GREFFONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type d'une interface pour l'intervention dans la gestion des greffons. */
+G_DEFINE_INTERFACE(GPluginManager, g_plugin_manager, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de gestion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plugin_manager_default_init(GPluginManagerInterface *iface)
+{
+ iface->handle_native = NULL;
+ iface->handle_all = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Accompagne la fin du chargement des modules natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginManagerInterface *iface; /* Interface utilisée */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ if (iface->handle_native != NULL)
+ iface->handle_native(manager);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Prend acte du chargement de l'ensemble des greffons. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginManagerInterface *iface; /* Interface utilisée */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ if (iface->handle_all != NULL)
+ iface->handle_all(manager);
+
+}
diff --git a/src/plugins/manager.h b/src/plugins/manager.h
new file mode 100644
index 0000000..2eb90a8
--- /dev/null
+++ b/src/plugins/manager.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.h - prototypes pour l'intervention dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_MANAGER_H
+#define _PLUGINS_MANAGER_H
+
+
+#include "../glibext/helpers.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+#define G_TYPE_PLUGIN_MANAGER (g_plugin_manager_get_type())
+
+DECLARE_INTERFACE(GPluginManager, g_plugin_manager, G, PLUGIN_MANAGER);
+
+
+/* Accompagne la fin du chargement des modules natifs. */
+void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *);
+
+/* Prend acte du chargement de l'ensemble des greffons. */
+void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *);
+
+
+
+/* -------------------- SOLLICITATION DES FONCTIONNALITES CREEES -------------------- */
+
+
+#define notify_native_plugins_loaded() \
+ process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \
+ g_plugin_manager_handle_native_plugins_loaded_event)
+
+#define notify_all_plugins_loaded() \
+ process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \
+ g_plugin_manager_handle_all_plugins_loaded_event)
+
+
+
+#endif /* _PLUGINS_MANAGER_H */
diff --git a/src/plugins/native-int.h b/src/plugins/native-int.h
new file mode 100644
index 0000000..575994f
--- /dev/null
+++ b/src/plugins/native-int.h
@@ -0,0 +1,73 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native-int.h - prototypes pour les structures internes des greffons natifs
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_NATIVE_INT_H
+#define _PLUGINS_NATIVE_INT_H
+
+
+#include "native.h"
+
+
+#include "plugin-int.h"
+
+
+
+/* Marqueur identifiable */
+#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de
+
+
+/* Greffon natif pour Chrysalide (instance) */
+struct _GNativePlugin
+{
+ GPluginModule parent; /* A laisser en premier */
+
+ /**
+ * Le module porte le code et les données en mémoire.
+ *
+ * Les fonctions *_dispose() et *_finalize() accompagnant la libération des
+ * greffons de la mémoire ne peuvent donc pas libérer ce module car elles
+ * scieraient la branche sur laquelle elles se trouvent.
+ *
+ * Par ailleurs, même s'ils sont conservés dans chaque greffon, les modules
+ * sont mis en place dans le code principal. C'est donc ce dernier qui les
+ * libère, dans la fonction on_plugin_ref_toggle().
+ */
+ GModule *module; /* Structure de chargement GLib*/
+
+};
+
+
+/* Greffon natif pour Chrysalide (classe) */
+struct _GNativePluginClass
+{
+ GPluginModuleClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un greffon natif. */
+bool g_native_plugin_create(GNativePlugin *, const char *, const char *, const char *, const char *, const char * const *, size_t, GModule *);
+
+
+
+#endif /* _PLUGINS_NATIVE_INT_H */
diff --git a/src/plugins/native.c b/src/plugins/native.c
new file mode 100644
index 0000000..de20abe
--- /dev/null
+++ b/src/plugins/native.c
@@ -0,0 +1,295 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native.c - interactions avec un greffon natif donné
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 "native.h"
+
+
+#include "native-int.h"
+#include "../common/cpp.h"
+
+
+
+/* ------------------------- COMPOSITION DE NOUVEAU GREFFON ------------------------- */
+
+
+/* Initialise la classe des greffons natifs. */
+static void g_native_plugin_class_init(GNativePluginClass *);
+
+/* Initialise une instance de greffon natif. */
+static void g_native_plugin_init(GNativePlugin *);
+
+/* Supprime toutes les références externes. */
+static void g_native_plugin_dispose(GNativePlugin *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_native_plugin_finalize(GNativePlugin *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Pointe le fichier contenant le greffon manipulé. */
+static char *g_native_plugin_get_filename(const GNativePlugin *);
+
+/* Fournit le nom brut associé au greffon. */
+static char *g_native_plugin_get_modname(const GNativePlugin *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COMPOSITION DE NOUVEAU GREFFON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un greffon Python. */
+G_DEFINE_TYPE(GNativePlugin, g_native_plugin, G_TYPE_PLUGIN_MODULE);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des greffons natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_class_init(GNativePluginClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GPluginModuleClass *plugin; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_native_plugin_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_native_plugin_finalize;
+
+ plugin = G_PLUGIN_MODULE_CLASS(class);
+
+ plugin->get_filename = (get_plugin_filename_fc)g_native_plugin_get_filename;
+ plugin->get_modname = (get_plugin_modname_fc)g_native_plugin_get_modname;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser. *
+* *
+* Description : Initialise une instance de greffon natif. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_init(GNativePlugin *plugin)
+{
+ plugin->module = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_dispose(GNativePlugin *plugin)
+{
+ G_OBJECT_CLASS(g_native_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_native_plugin_finalize(GNativePlugin *plugin)
+{
+ G_OBJECT_CLASS(g_native_plugin_parent_class)->finalize(G_OBJECT(plugin));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser pleinement. *
+* name = nom du greffon pour référence, principalement. *
+* desc = présentation éventuelle à destination humaine. *
+* version = indication de version éventuelle. *
+* url = référence vers une ressource en ligne. *
+* required = liste de dépendances éventuelles ou NULL. *
+* count = taille de cette liste. *
+* module = extension vue du système. *
+* *
+* Description : Met en place un greffon natif. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : Le transfert de propriétée du module est total. *
+* *
+******************************************************************************/
+
+bool g_native_plugin_create(GNativePlugin *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count, GModule *module)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_plugin_module_create(G_PLUGIN_MODULE(plugin), name, desc, version, url, required, count);
+
+ if (result)
+ plugin->module = module;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Renvoie la structure opaque associée au module en mémoire. *
+* *
+* Retour : Structure de chargement côté GLib. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GModule *g_native_plugin_get_module(const GNativePlugin *plugin)
+{
+ GModule *result; /* Accès au module à renvoyer */
+
+ result = plugin->module;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Pointe le fichier contenant le greffon manipulé. *
+* *
+* Retour : Chemin d'accès au greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_native_plugin_get_filename(const GNativePlugin *plugin)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+
+ result = strdup(g_module_name(plugin->module));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à valider. *
+* *
+* Description : Fournit le nom brut associé au greffon. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_native_plugin_get_modname(const GNativePlugin *plugin)
+{
+ char *result; /* Désignation brute à renvoyer*/
+ char *path; /* Chemin à traiter */
+ char *filename; /* Nom de bibliothèque partagée*/
+ size_t length; /* Taille du nom */
+ int ret; /* Bilan d'une comparaison */
+
+ path = g_native_plugin_get_filename(plugin);
+
+ filename = basename(path);
+
+ if (strncmp(filename, "lib", 3) == 0)
+ filename += 3;
+
+ length = strlen(filename);
+
+#ifdef _WIN32
+# define SHARED_SUFFIX ".dll"
+#else
+# define SHARED_SUFFIX ".so"
+#endif
+
+ if (length >= STATIC_STR_SIZE(SHARED_SUFFIX))
+ {
+ ret = strncmp(&filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)],
+ SHARED_SUFFIX,
+ STATIC_STR_SIZE(SHARED_SUFFIX));
+
+ if (ret == 0)
+ filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)] = '\0';
+
+ }
+
+ result = strdup(filename);
+
+ free(path);
+
+ return result;
+
+}
diff --git a/src/plugins/native.h b/src/plugins/native.h
new file mode 100644
index 0000000..18039c8
--- /dev/null
+++ b/src/plugins/native.h
@@ -0,0 +1,46 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native.h - prototypes pour les interactions avec un greffon natif donné
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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_NATIVE_H
+#define _PLUGINS_NATIVE_H
+
+
+#include <gmodule.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define G_TYPE_NATIVE_PLUGIN (g_native_plugin_get_type())
+
+DECLARE_GTYPE(GNativePlugin, g_native_plugin, G, NATIVE_PLUGIN);
+
+
+/* Renvoie la structure opaque associée au module en mémoire. */
+GModule *g_native_plugin_get_module(const GNativePlugin *);
+
+
+
+#endif /* _PLUGINS_NATIVE_H */
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index 6b36d2f..3e107b8 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -30,19 +30,29 @@
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <i18n.h>
-#include "dt.h"
+#include "manager.h"
+#include "native.h"
#include "plugin-int.h"
+#include "../common/cpp.h"
#include "../common/extstr.h"
#include "../core/logs.h"
+#include "../core/nox.h"
#include "../core/paths.h"
+/**
+ * Prototype de la fonction de création, à garder synchronisé avec
+ * NATIVE_PLUGIN_ENTRYPOINT() (cf. native-int.h).
+ */
+typedef GPluginModule * (* get_plugin_instance_cb) (GModule *);
+
/* Liste de l'ensemble des greffons */
static GPluginModule **_pg_list = NULL;
static size_t _pg_count = 0;
@@ -60,6 +70,9 @@ static void browse_directory_for_plugins(const char *);
/* Suit les variations du compteur de références d'un greffon. */
static void on_plugin_ref_toggle(gpointer, GPluginModule *, gboolean);
+/* Fournit le greffon répondant à un nom donné. */
+static GPluginModule *_find_plugin_by_name(const char *, size_t *);
+
/******************************************************************************
@@ -82,8 +95,7 @@ bool init_all_plugins(bool load)
char *saveptr; /* Sauvegarde pour parcours */
char *udir; /* Répertoire supplémentaire ? */
- result = init_chrysalide_dynamic_types();
- if (!result) goto exit;
+ result = true;
g_rw_lock_init(&_pg_lock);
@@ -107,8 +119,6 @@ bool init_all_plugins(bool load)
if (load)
load_remaning_plugins();
- exit:
-
return result;
}
@@ -129,64 +139,22 @@ bool init_all_plugins(bool load)
void exit_all_plugins(void)
{
size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Définition du greffon */
lock_plugin_list_for_reading();
- if (_pg_list != NULL)
+ for (i = 0; i < _pg_count; i++)
{
- for (i = 0; i < _pg_count; i++)
- {
- assert(_pg_list[i] != NULL);
-
- /**
- * Si le greffon a conduit à la mise en place d'autres greffons, le
- * système de dépendances ne suffit pas pour le décompte des références :
- * le greffon voit à un instant T son compteur décroître ici ; à un
- * instant T+1, un greffon fils décrémente à son tour le compteur vers
- * le greffon principal.
- *
- * Le compteur du conteneur tombe alors à 0, et le code correspondant
- * est retiré. Lorsque que le flot d'exécution revient à la procédure
- * de sortie du second greffon, son code n'est plus en mémoire.
- *
- * On s'assure donc que les greffons qui génèrent d'autres greffons
- * sont bien traités en dernier.
- */
-
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- if (pg_iface != NULL && pg_iface->container)
- g_object_ref(_pg_list[i]);
-
- g_object_unref(_pg_list[i]);
-
- }
-
- for (i = 0; i < _pg_count; i++)
- {
- if (_pg_list[i] == NULL)
- continue;
-
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- if (pg_iface == NULL || !pg_iface->container)
- continue;
-
- g_object_unref(_pg_list[i]);
-
- }
+ assert(_pg_list[i] != NULL);
+ unref_object(_pg_list[i]);
+ }
+ if (_pg_list != NULL)
free(_pg_list);
- }
-
unlock_plugin_list_for_reading();
g_rw_lock_clear(&_pg_lock);
- exit_chrysalide_dynamic_types();
-
}
@@ -243,63 +211,95 @@ static int filter_dirs_or_mods(const struct dirent *entry)
* *
* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Part à la recherche de greffons sous forme de modules. *
+* Description : Indique la version (NOX/UI) associée à un nom de fichier. *
* *
-* Retour : - *
+* Retour : true si la version complémentaire existe ou false. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void browse_directory_for_plugins(const char *dir)
+static bool check_for_plugin_versions(const char *dir, const char *filename, bool *is_nox, bool *is_ui)
{
- struct dirent **namelist; /* Eléments trouvés */
- int ret; /* Bilan du parcours */
- char *filename; /* Elément à ausculter */
- GPluginModule *plugin; /* Greffon à intégrer ou pas */
+ bool result; /* Bilan à renvoyer */
+ size_t length; /* Taille du nom de fichier */
+ char *alt_path; /* Autre chemin complet testé */
+ int ret; /* Bilan d'une impression */
- ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
- if (ret < 0)
- {
- LOG_ERROR_N("scandir");
- return;
- }
+#ifdef _WIN32
+# define SHARED_SUFFIX ".dll"
+#else
+# define SHARED_SUFFIX ".so"
+#endif
+#define UI_SHARED_SUFFIX "ui" SHARED_SUFFIX
+
+ result = false;
+
+ /* Propriétés du fichier courant */
- while (ret--)
+ length = strlen(filename);
+
+ if (length < STATIC_STR_SIZE(UI_SHARED_SUFFIX))
+ *is_ui = false;
+
+ else
+ *is_ui = (strcmp(filename + length - STATIC_STR_SIZE(UI_SHARED_SUFFIX), UI_SHARED_SUFFIX) == 0);
+
+ if (*is_ui)
+ *is_nox = false;
+
+ else
{
- filename = (char *)calloc(strlen(dir) + 1 + strlen(namelist[ret]->d_name) + 1, sizeof(char));
+ if (length < STATIC_STR_SIZE(SHARED_SUFFIX))
+ *is_nox = false;
- strcpy(filename, dir);
- strcat(filename, G_DIR_SEPARATOR_S);
- strcat(filename, namelist[ret]->d_name);
+ else
+ *is_nox = (strcmp(filename + length - STATIC_STR_SIZE(SHARED_SUFFIX), SHARED_SUFFIX) == 0);
- if (namelist[ret]->d_type == DT_DIR)
- browse_directory_for_plugins(filename);
+ }
+
+ /* Recherche d'une version alternative */
+
+ if (*is_nox || *is_ui)
+ {
+ if (*is_nox)
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ UI_SHARED_SUFFIX);
else
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ SHARED_SUFFIX);
+
+ if (ret <= 0)
{
- plugin = g_plugin_module_new(filename);
+ LOG_ERROR_N("asprintf");
+ goto exit;
+ }
- if (plugin != NULL)
- register_plugin(plugin);
+ ret = access(alt_path, R_OK | X_OK);
- }
+ result = (ret == 0);
- free(filename);
- free(namelist[ret]);
+ free(alt_path);
}
- free(namelist);
+ exit:
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à ajouter aux autres disponibles. *
+* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Ajoute un greffon à la liste principale de greffons. *
+* Description : Part à la recherche de greffons sous forme de modules. *
* *
* Retour : - *
* *
@@ -307,52 +307,91 @@ static void browse_directory_for_plugins(const char *dir)
* *
******************************************************************************/
-void _register_plugin(GPluginModule *plugin)
+static void browse_directory_for_plugins(const char *dir)
{
- size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Informations à consulter */
- const char *name; /* Désignation du greffon */
-
- /**
- * L'appel sans verrou n'est fourni que pour les greffons
- * mettant en place des greffons en interne !
- */
-
- /* Recherche d'un éventuel doublon */
+ struct dirent **namelist; /* Eléments trouvés */
+ int ret; /* Bilan d'un appel */
+ int k; /* Boucle de parcours */
+ bool nox_mode; /* Absence de support graphique*/
+ char *filename; /* Elément à ausculter */
+ bool is_nox; /* Chemin de version basique ? */
+ bool is_ui; /* Chemin de version graphique */
+ bool has_alt; /* Existence d'une alternative */
+ GModule *module; /* Abstration de manipulation */
+ get_plugin_instance_cb get_instance; /* Point d'entrée exporté */
+ GPluginModule *plugin; /* Greffon à intégrer ou pas */
- pg_iface = g_plugin_module_get_interface(plugin);
+ ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
+ if (ret < 0)
+ {
+ LOG_ERROR_N("scandir");
+ return;
+ }
- name = pg_iface->name;
+ nox_mode = run_in_nox_mode();
- for (i = 0; i < _pg_count; i++)
+ for (k = ret; k--; )
{
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- if (strcmp(name, pg_iface->name) == 0)
+ ret = asprintf(&filename, "%s%s%s", dir, G_DIR_SEPARATOR_S, namelist[k]->d_name);
+ if (ret <= 0)
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' already registered!"), name);
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
- break;
+ if (namelist[k]->d_type == DT_DIR)
+ browse_directory_for_plugins(filename);
- }
+ else
+ {
+ has_alt = check_for_plugin_versions(dir, namelist[k]->d_name, &is_nox, &is_ui);
- }
+ if ((nox_mode && is_nox) || (!nox_mode && ((is_nox && !has_alt) || is_ui)))
+ {
+ module = g_module_open(filename, G_MODULE_BIND_LAZY);
+ if (module == NULL)
+ {
+ log_variadic_message(LMT_ERROR,
+ _("Error while loading the plugin candidate '%s' : %s"),
+ filename, g_module_error());
+ goto next_file;
+ }
+
+ get_instance = NULL;
+
+ if (!g_module_symbol(module, "get_chrysalide_plugin_instance", (gpointer *)&get_instance))
+ log_variadic_message(LMT_ERROR,
+ _("No '%s' entry in plugin candidate '%s'"),
+ "<sym>", filename);
+
+ if (get_instance == NULL)
+ plugin = NULL;
+ else
+ plugin = get_instance(module);
+
+ if (plugin != NULL)
+ {
+ register_plugin(plugin);
+ unref_object(plugin);
+ }
+
+ else
+ g_module_close(module);
- /* Ajout du greffon à la liste */
+ }
+ else
+ log_variadic_message(LMT_INFO, _("Skipping unsuitable file for plugin: %s"), filename);
- if (i == _pg_count)
- {
- _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+ }
- _pg_list[_pg_count - 1] = plugin;
+ next_file:
- g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+ free(filename);
+ free(namelist[k]);
}
- else
- /* FIXME : leak(plugin); */;
+ free(namelist);
}
@@ -373,24 +412,55 @@ void _register_plugin(GPluginModule *plugin)
static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolean last)
{
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *name; /* Désignation du greffon */
size_t index; /* Indice du greffon */
GPluginModule *same; /* Juste pour la récupération */
+ GModule *module; /* Structure de chargement GLib*/
if (last)
{
assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE);
- pg_iface = g_plugin_module_get_interface(plugin);
+ name = g_plugin_module_get_name(plugin);
+
+ /**
+ * Les mécanismes de g_object_unref() prennent en compte la bascule d'un
+ * compteur de références initialement à 2 avant appel pour déclencher
+ * cet appel à on_plugin_ref_toggle() mis en place par g_object_add_toggle_ref().
+ *
+ * Incrémenter ce compteur à nouveau, via get_plugin_by_name(), puis le
+ * décrémenter ensuite via unref_object() va conduire à une nouvelle
+ * bascule des statuts de suivi dans g_object_unref().
+ *
+ * Il est ainsi impératif de rechercher une instance du greffon dans
+ * la liste des extensions sans toucher au compteur de références.
+ */
+
+ same = _find_plugin_by_name(name, &index);
- same = get_plugin_by_name(pg_iface->name, &index);
assert(same != NULL);
+ assert(same == plugin);
_pg_list[index] = NULL;
- g_object_remove_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+ /**
+ * Suppression de la dernière référence.
+ */
- g_object_unref(G_OBJECT(same));
+ if (G_IS_NATIVE_PLUGIN(plugin))
+ module = g_native_plugin_get_module(G_NATIVE_PLUGIN(plugin));
+ else
+ module = NULL;
+
+ g_object_remove_toggle_ref(G_OBJECT(same), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ /**
+ * Plus aucun code issu du greffon n'est désormais utile. Le module associé peut
+ * être libéré de la mémoire.
+ */
+
+ if (module != NULL)
+ g_module_close(module);
}
@@ -411,9 +481,40 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea
void register_plugin(GPluginModule *plugin)
{
+ size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation du greffon */
+ const char *existing; /* Nom d'un greffon en place */
+
g_rw_lock_writer_lock(&_pg_lock);
- _register_plugin(plugin);
+ /* Recherche d'un éventuel doublon */
+
+ name = g_plugin_module_get_name(plugin);
+
+ for (i = 0; i < _pg_count; i++)
+ {
+ existing = g_plugin_module_get_name(_pg_list[i]);
+
+ if (strcmp(name, existing) == 0)
+ {
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' already registered!"), name);
+ break;
+ }
+
+ }
+
+ /* Ajout du greffon à la liste */
+
+ if (i == _pg_count)
+ {
+ _pg_list = realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+
+ _pg_list[_pg_count - 1] = plugin;
+ ref_object(plugin);
+
+ g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ }
g_rw_lock_writer_unlock(&_pg_lock);
@@ -481,13 +582,18 @@ void load_remaning_plugins(void)
/* Supprime les greffons non chargés */
- for (i = 0; i < _pg_count; i++)
+ for (i = 0; i < _pg_count;)
{
flags = g_plugin_module_get_flags(_pg_list[i]);
- if ((flags & PSF_LOADED) == 0)
+ if (flags & PSF_LOADED)
+ i++;
+
+ else
{
- g_object_unref(G_OBJECT(_pg_list[i]));
+ unref_object(_pg_list[i]);
+
+ assert(_pg_list[i] == NULL);
memmove(&_pg_list[i], &_pg_list[i + 1], (_pg_count - i - 1) * sizeof(GPluginModule *));
_pg_count--;
@@ -514,15 +620,16 @@ void load_remaning_plugins(void)
* *
* Retour : Instance du greffon trouvé ou NULL si aucun. *
* *
-* Remarques : - *
+* Remarques : Le compteur de référence d'un greffon trouvé n'est pas *
+* modifié. *
* *
******************************************************************************/
-GPluginModule *get_plugin_by_name(const char *name, size_t *index)
+static GPluginModule *_find_plugin_by_name(const char *name, size_t *index)
{
GPluginModule *result; /* Greffon trouvé à renvoyer */
size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *current; /* Nom du greffon courant */
result = NULL;
@@ -536,9 +643,9 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
/* Si on est en train de procéder à un nettoyage... */
if (_pg_list[i] == NULL) continue;
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+ current = g_plugin_module_get_name(_pg_list[i]);
- if (strcmp(pg_iface->name, name) == 0)
+ if (strcmp(current, name) == 0)
{
result = _pg_list[i];
@@ -549,9 +656,6 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
}
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
return result;
}
@@ -559,33 +663,25 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
/******************************************************************************
* *
-* Paramètres : count = nombre de greffons trouvés. [OUT] *
+* Paramètres : name = désignation du greffon recherché. *
+* index = indice du greffon trouvé. [OUT] *
* *
-* Description : Fournit la liste de l'ensemble des greffons. *
+* Description : Fournit le greffon répondant à un nom donné. *
* *
-* Retour : Liste de tous les greffons chargés. *
+* Retour : Instance du greffon trouvé ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule **get_all_plugins(size_t *count)
+GPluginModule *get_plugin_by_name(const char *name, size_t *index)
{
- GPluginModule **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours */
-
- g_rw_lock_reader_lock(&_pg_lock);
-
- result = malloc(_pg_count * sizeof(GPluginModule *));
- *count = _pg_count;
+ GPluginModule *result; /* Greffon trouvé à renvoyer */
- for (i = 0; i < _pg_count; i++)
- {
- result[i] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
- }
+ result = _find_plugin_by_name(name, index);
- g_rw_lock_reader_unlock(&_pg_lock);
+ if (result != NULL)
+ ref_object(result);
return result;
@@ -594,48 +690,30 @@ GPluginModule **get_all_plugins(size_t *count)
/******************************************************************************
* *
-* Paramètres : action = fonctionnalité recherchée. *
-* count = nombre de greffons trouvés. [OUT] *
+* Paramètres : count = nombre de greffons trouvés. [OUT] *
* *
-* Description : Fournit les greffons offrant le service demandé. *
+* Description : Fournit la liste de l'ensemble des greffons. *
* *
-* Retour : Liste de greffons correspondants issue d'un tri interne. *
+* Retour : Liste de tous les greffons chargés. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count)
+GPluginModule **get_all_plugins(size_t *count)
{
GPluginModule **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours #1 */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t j; /* Boucle de parcours #2 */
-
- result = NULL;
- *count = 0;
+ size_t i; /* Boucle de parcours */
g_rw_lock_reader_lock(&_pg_lock);
+ result = malloc(_pg_count * sizeof(GPluginModule *));
+ *count = _pg_count;
+
for (i = 0; i < _pg_count; i++)
{
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- for (j = 0; j < pg_iface->actions_count; j++)
- {
- if (pg_iface->actions[j] == action)
- {
- result = realloc(result, ++(*count) * sizeof(GPluginModule *));
-
- result[*count - 1] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
-
- break;
-
- }
-
- }
-
+ result[i] = _pg_list[i];
+ ref_object(result[i]);
}
g_rw_lock_reader_unlock(&_pg_lock);
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index 83e9091..777b19c 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -52,9 +52,6 @@ void _lock_unlock_plugin_list_for_reading(bool lock);
#define unlock_plugin_list_for_reading() _lock_unlock_plugin_list_for_reading(false)
/* Ajoute un greffon à la liste principale de greffons. */
-void _register_plugin(GPluginModule *);
-
-/* Ajoute un greffon à la liste principale de greffons. */
void register_plugin(GPluginModule *);
/* Charge tous les greffons restant à charger. */
@@ -66,16 +63,74 @@ GPluginModule *get_plugin_by_name(const char *, size_t *);
/* Fournit la liste de l'ensemble des greffons. */
GPluginModule **get_all_plugins(size_t *);
-/* Fournit les greffons offrant le service demandé. */
-GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
-
/**
* Définitions des opérations appliquables à une catégories de greffons.
*/
-#define process_all_plugins_for(a, f, ...) \
+#define process_all_plugins_for(tp, cst, fc) \
+ do \
+ { \
+ size_t __count; \
+ GPluginModule **__list; \
+ size_t __i; \
+ GPluginModule *__pg; \
+ __list = get_all_plugins(&__count); \
+ for (__i = 0; __i < __count; __i++) \
+ { \
+ __pg = __list[__i]; \
+ if (G_TYPE_CHECK_INSTANCE_TYPE(__pg, tp)) \
+ fc(cst(__pg)); \
+ unref_object(__pg); \
+ } \
+ if (__list != NULL) \
+ free(__list); \
+ } \
+ while (0)
+
+#define accumulate_from_all_plugins(tp, cst, fc, atp, cnt) \
+ ({ \
+ atp *__acc_list; \
+ size_t __count; \
+ GPluginModule **__list; \
+ size_t __i; \
+ GPluginModule *__pg; \
+ size_t __tmp_count; \
+ atp *__tmp_list; \
+ *cnt = 0; \
+ __acc_list = NULL; \
+ __list = get_all_plugins(&__count); \
+ for (__i = 0; __i < __count; __i++) \
+ { \
+ __pg = __list[__i]; \
+ if (G_TYPE_CHECK_INSTANCE_TYPE(__pg, tp)) \
+ { \
+ __tmp_list = fc(cst(__pg), &__tmp_count); \
+ if (__tmp_list != NULL) \
+ { \
+ __acc_list = realloc(__acc_list, \
+ (*cnt + __tmp_count) * sizeof(atp)); \
+ memcpy(&__acc_list[*cnt], __tmp_list, \
+ __tmp_count * sizeof(atp)); \
+ *cnt += __tmp_count; \
+ free(__tmp_list); \
+ } \
+ } \
+ unref_object(__pg); \
+ } \
+ if (__list != NULL) \
+ free(__list); \
+ __acc_list; \
+ })
+
+
+
+#if 0
+
+// TODO : REMME
+
+#define process_all_plugins_for_old__(a, f, ...) \
do \
{ \
size_t __count; \
@@ -114,11 +169,13 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
/* DPS_PG_MANAGEMENT */
+/*
#define notify_native_plugins_loaded() \
- process_all_plugins_for(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+ process_all_plugins_for_old__(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
#define notify_all_plugins_loaded() \
- process_all_plugins_for(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+ process_all_plugins_for_old__(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+*/
#define build_type_instance(t) \
process_plugins_while_null(PGA_TYPE_BUILDING, g_plugin_module_build_type_instance, t)
@@ -126,44 +183,47 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
/* DPS_SETUP */
#define include_plugin_theme(d, r, c) \
- process_all_plugins_for(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c)
+ process_all_plugins_for_old__(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c)
/* DPS_RUNNING */
#define notify_panel_creation(i) \
- process_all_plugins_for(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i)
+ process_all_plugins_for_old__(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i)
#define notify_panel_docking(i, d) \
- process_all_plugins_for(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d)
+ process_all_plugins_for_old__(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d)
/* DPS_CONTENT */
#define handle_binary_content(a, c, i, s) \
- process_all_plugins_for(a, g_plugin_module_handle_binary_content, c, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_binary_content, c, i, s)
#define handle_loaded_content(a, c, i, s) \
- process_all_plugins_for(a, g_plugin_module_handle_loaded_content, c, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_loaded_content, c, i, s)
/* DPS_FORMAT */
#define handle_known_format_analysis(a, f, g, s) \
- process_all_plugins_for(a, g_plugin_module_handle_known_format_analysis, f, g, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_known_format_analysis, f, g, s)
#define preload_binary_format(a, f, i, s) \
- process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_preload_binary_format, f, i, s)
#define attach_debug_format(f) \
- process_all_plugins_for(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f)
+ process_all_plugins_for_old__(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f)
/* DPS_DISASSEMBLY */
#define process_disassembly_event(a, b, s, c) \
- process_all_plugins_for(a, g_plugin_module_process_disassembly_event, b, s, c)
+ process_all_plugins_for_old__(a, g_plugin_module_process_disassembly_event, b, s, c)
/* DPS_DETECTION */
#define detect_external_tools(a, cnt, v, n, c) \
- process_all_plugins_for(a, g_plugin_module_detect_external_tools, cnt, v, n, c)
+ process_all_plugins_for_old__(a, g_plugin_module_detect_external_tools, cnt, v, n, c)
+
+
+#endif
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 1118140..b5e0b51 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -35,18 +35,6 @@
/* ------------------------ IDENTIFICATION DE COMPATIBILITES ------------------------ */
-/* Version identifiant les définitions courantes */
-typedef uint32_t plugin_abi_version_t;
-
-#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \
- (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff))
-
-#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff)
-#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
-#define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
-
-#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 3, 0)
-
/* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
@@ -232,14 +220,14 @@ typedef enum _PluginAction
/* ------------------------ PREMIER INTERFACAGE PROTOCOLAIRE ------------------------ */
-#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull
+//#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull
/* Définition d'un greffon */
typedef struct _plugin_interface
{
uint64_t magic; /* Vérification a minima */
- plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+ uint32_t /*plugin_abi_version_t*/ abi_version; /* Version du protocole utilisé*/
/**
* Les champs suivants ne sont généralement pas alloués dynamiquement,
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 3ba19dc..07b455a 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -37,21 +37,28 @@
#include "../common/bits.h"
-/* Transfert de la conscience de soi. */
-typedef void (* pg_set_self_fc) (GPluginModule *);
-/* Prend acte du [dé]chargement du greffon. */
+/* Pointe le fichier contenant le greffon manipulé. */
+typedef char * (* get_plugin_filename_fc) (const GPluginModule *);
+
+/* Fournit le nom brut associé au greffon. */
+typedef char * (* get_plugin_modname_fc) (const GPluginModule *);
+
+/* Prend acte de (l'|la dés)activation du greffon. */
typedef bool (* pg_management_fc) (GPluginModule *);
+
+
+
+/* Transfert de la conscience de soi. */
+typedef void (* pg_set_self_fc) (GPluginModule *);
+
/* Accompagne la fin du chargement des modules natifs. */
typedef void (* pg_plugins_loaded_fc) (GPluginModule *, PluginAction);
/* Crée une instance à partir d'un type dynamique externe. */
typedef gpointer (* pg_build_instance_fc) (GPluginModule *, PluginAction, GType);
-/* Fournit le nom brut associé au greffon. */
-typedef char * (* pg_get_modname_fc) (const GPluginModule *);
-
#if 0
/* Procède à une opération liée à un contenu binaire. */
@@ -90,22 +97,47 @@ typedef void (* pg_detect_tools_fc) (const GPluginModule *, PluginAction, const
#endif
+/* Marqueur identifiable */
+#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de
+
+
+/* Version identifiant les définitions courantes */
+typedef uint32_t plugin_abi_version_t;
+
+#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \
+ (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff))
+
+#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff)
+#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
+#define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
+
+/**
+ * 0.3.0 : dernière version avec actions et fonctions associées
+ * 1.0.0 (04/01/25) : bascule en chargement d'objet et interfaces
+ */
+#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(1, 0, 0)
+
+
/* Greffon pour Chrysalide (instance) */
struct _GPluginModule
{
GObject parent; /* A laisser en premier */
- char *filename; /* Fichier associé au greffon */
- GModule *module; /* Abstration de manipulation */
+ uint32_t magic; /* Vérification a minima */
+ plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+
+ char *name; /* Désignation humaine courte */
+ char *desc; /* Description plus loquace */
+ char *version; /* Version du greffon */
+ char *url; /* Site Web associé */
- const plugin_interface *interface; /* Déclaration d'interfaçage */
+ char **required; /* Pré-chargements requis */
+ size_t required_count; /* Quantité de ces dépendances */
PluginStatusFlags flags; /* Fanion pour l'état courant */
bitfield_t *dependencies; /* Cartographie des dépendances*/
- //GGenConfig *config; /* Configuration dédiée */
-
};
@@ -114,6 +146,18 @@ struct _GPluginModuleClass
{
GObjectClass parent; /* A laisser en premier */
+ get_plugin_filename_fc get_filename; /* Obtention du chemin */
+ get_plugin_modname_fc get_modname; /* Fourniture du nom brut */
+
+ pg_management_fc enable; /* Procédure d'activation */
+ pg_management_fc disable; /* Procédure d'extinction */
+
+
+
+ /////////////////////////////////////////////
+
+#if 0
+
pg_management_fc init; /* Procédure d'initialisation */
pg_management_fc manage; /* Etape dans la vie du greffon*/
pg_management_fc exit; /* Procédure d'extinction */
@@ -121,8 +165,6 @@ struct _GPluginModuleClass
pg_plugins_loaded_fc plugins_loaded; /* Fin des chargements */
pg_build_instance_fc build_instance; /* Création d'objets */
- pg_get_modname_fc get_modname; /* Fourniture du nom brut */
-
#if 0
#ifdef INCLUDE_GTK_SUPPORT
pg_include_theme_fc include_theme; /* Extension d'un thème */
@@ -141,12 +183,28 @@ struct _GPluginModuleClass
pg_detect_tools_fc detect; /* Lancement de détections */
#endif
+#endif
+
+ /////////////////////////////////////////////
+
};
-/* Met en place la configuration dédiée au greffon. */
-void g_plugin_module_create_config(GPluginModule *);
+
+#define STORE_PLUGIN_ABI(p) \
+ do \
+ { \
+ GPluginModule *_p; \
+ _p = G_PLUGIN_MODULE(p); \
+ _p->magic = CHRYSALIDE_PLUGIN_MAGIC; \
+ _p->abi_version = CURRENT_ABI_VERSION; \
+ } \
+ while (0);
+
+
+/* Met en place un greffon. */
+bool g_plugin_module_create(GPluginModule *, const char *, const char *, const char *, const char *, const char * const *, size_t);
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 5b3e475..dfdf3ed 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -30,14 +30,13 @@
#include <libgen.h>
#include <malloc.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include "dt.h"
#include "pglist.h"
#include "plugin-int.h"
+#include "../common/compiler.h"
#include "../common/extstr.h"
#include "../common/pathname.h"
#include "../common/xdg.h"
@@ -56,19 +55,12 @@ static void g_plugin_module_dispose(GPluginModule *);
/* Procède à la libération totale de la mémoire. */
static void g_plugin_module_finalize(GPluginModule *);
-/* Initialise la classe des greffons d'extension. */
-static void g_plugin_module_init_gclass(GPluginModuleClass *, GModule *);
-
-/* Fournit le nom brut associé au greffon. */
-static char *_g_plugin_module_get_modname(const GPluginModule *);
-
/* Indique le type défini pour un greffon. */
G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
-
/******************************************************************************
* *
* Paramètres : class = classe à initialiser. *
@@ -84,16 +76,17 @@ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
static void g_plugin_module_class_init(GPluginModuleClass *class)
{
GObjectClass *object; /* Autre version de la classe */
- GPluginModuleClass *plugin; /* Version parente de la classe*/
object = G_OBJECT_CLASS(class);
object->dispose = (GObjectFinalizeFunc/* ! */)g_plugin_module_dispose;
object->finalize = (GObjectFinalizeFunc)g_plugin_module_finalize;
- plugin = G_PLUGIN_MODULE_CLASS(class);
+ class->get_filename = NULL;
+ class->get_modname = NULL;
- plugin->get_modname = (pg_get_modname_fc)_g_plugin_module_get_modname;
+ class->enable = NULL;
+ class->disable = NULL;
}
@@ -112,7 +105,17 @@ static void g_plugin_module_class_init(GPluginModuleClass *class)
static void g_plugin_module_init(GPluginModule *plugin)
{
- //plugin->config = NULL;
+ plugin->name = NULL;
+ plugin->desc = NULL;
+ plugin->version = NULL;
+ plugin->url = NULL;
+
+ plugin->required = NULL;
+ plugin->required_count = 0;
+
+ plugin->flags = PSF_NONE;
+
+ plugin->dependencies = NULL;
}
@@ -131,29 +134,29 @@ static void g_plugin_module_init(GPluginModule *plugin)
static void g_plugin_module_dispose(GPluginModule *plugin)
{
- const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
+ size_t index; /* Indice de greffon visé */
GPluginModule *dependency; /* Module nécessaire */
GPluginModuleClass *class; /* Classe de l'instance active */
- pg_iface = g_plugin_module_get_interface(plugin);
-
- if (pg_iface != NULL)
+ if (plugin->dependencies != NULL)
{
lock_plugin_list_for_reading();
- for (i = 0; i < pg_iface->required_count; i++)
+ for (i = 0; i < plugin->required_count; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+ dependency = get_plugin_by_name(plugin->required[i], &index);
- /* Si le chargement a bien été complet avant la sortie... */
- if (dependency != NULL)
+ /* Si la dépendance a bien été pris en compte... */
+ if (test_in_bit_field(plugin->dependencies, index))
{
+ assert(dependency != NULL);
+
/* Un coup pour l'appel à get_plugin_by_name(). */
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
/* Un coup pour la dépendance */
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -163,25 +166,13 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
}
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- if (class->exit != NULL)
- class->exit(plugin);
-
- /*
- if (plugin->config != NULL)
+ if (plugin->flags & PSF_LOADED)
{
- g_generic_config_write(plugin->config);
-
- g_clear_object(&plugin->config);
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- }
- */
+ if (class->disable != NULL)
+ class->disable(plugin);
- if (plugin->module != NULL)
- {
- g_module_close(plugin->module);
- plugin->module = NULL;
}
G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin));
@@ -203,7 +194,25 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
static void g_plugin_module_finalize(GPluginModule *plugin)
{
- free(plugin->filename);
+ size_t i; /* Boucle de parcours */
+
+ if (plugin->name != NULL)
+ free(plugin->name);
+
+ if (plugin->desc != NULL)
+ free(plugin->desc);
+
+ if (plugin->version != NULL)
+ free(plugin->version);
+
+ if (plugin->url != NULL)
+ free(plugin->url);
+
+ for (i = 0; i < plugin->required_count; i++)
+ free(plugin->required[i]);
+
+ if (plugin->required != NULL)
+ free(plugin->required);
if (plugin->dependencies != NULL)
delete_bit_field(plugin->dependencies);
@@ -215,627 +224,173 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
/******************************************************************************
* *
-* Paramètres : filename = nom du fichier à charger. *
+* Paramètres : plugin = instance à initialiser pleinement. *
+* name = nom du greffon pour référence, principalement. *
+* desc = présentation éventuelle à destination humaine. *
+* version = indication de version éventuelle. *
+* url = référence vers une ressource en ligne. *
+* required = liste de dépendances éventuelles ou NULL. *
+* count = taille de cette liste. *
* *
-* Description : Crée un module pour un greffon donné. *
+* Description : Met en place un greffon. *
* *
-* Retour : Adresse de la structure mise en place. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule *g_plugin_module_new(const gchar *filename)
+bool g_plugin_module_create(GPluginModule *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count)
{
- GPluginModule *result; /* Structure à retourner */
- GModule *module; /* Abstration de manipulation */
- pg_set_self_fc set_self; /* Copie du greffon */
- const plugin_interface *interface; /* Déclaration d'interfaçage */
- plugin_abi_version_t current; /* Version de l'ABI actuelle */
- bool valid; /* Statut de validité */
- size_t i; /* Boucle de parcours */
- uint32_t action; /* Identifiant d'une action */
- uint32_t category; /* Catégorie principale */
- uint32_t sub; /* Sous-catégorie visée */
- GType gtype; /* Nouveau type de greffon */
-
- module = g_module_open(filename, G_MODULE_BIND_LAZY);
- if (module == NULL)
- {
- log_variadic_message(LMT_ERROR,
- _("Error while loading the plugin candidate '%s' : %s"),
- filename, g_module_error());
- goto bad_module;
- }
-
-
-#define load_plugin_symbol(mod, sym, dest) \
- ({ \
- bool __result; \
- if (!g_module_symbol(mod, sym, (gpointer *)dest)) \
- { \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- sym, filename); \
- __result = false; \
- } \
- else __result = true; \
- __result; \
- })
-
-
- /* Récupération de la version d'ABI */
-
- if (!load_plugin_symbol(module, "chrysalide_plugin_set_self", &set_self))
- goto no_self_setter;
-
- if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface))
- goto no_interface;
-
- current = CURRENT_ABI_VERSION;
-
- if (current != interface->abi_version)
- goto wrong_abi;
-
- /* Localisation des différents points d'entrée déclarés */
-
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ size_t k; /* Boucle de parcours #2 */
-#define check_plugin_symbol(mod, sym) \
- ({ \
- bool __result; \
- __result = g_module_symbol(mod, sym, (gpointer []) { NULL }); \
- if (!__result) \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- sym, filename); \
- __result; \
- })
+ /* Validations préalables */
+ assert(name != NULL);
- valid = true;
+ result = (name != NULL);
- for (i = 0; i < interface->actions_count && valid; i++)
+ if (result && plugin->abi_version != CURRENT_ABI_VERSION)
{
- action = interface->actions[i];
- category = MASK_PLUGIN_CATEGORY(action);
- sub = MASK_PLUGIN_SUB_CATEGORY(action);
-
- switch (category)
- {
- case DPC_BASIC:
-
- switch (sub)
- {
- case DPS_NONE:
- break;
-
- case DPS_PG_MANAGEMENT:
-
- switch (action)
- {
- case PGA_PLUGIN_INIT:
- valid = check_plugin_symbol(module, "chrysalide_plugin_init");
- break;
-
- case PGA_PLUGIN_LOADED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_manage");
- break;
-
- case PGA_PLUGIN_EXIT:
- valid = check_plugin_symbol(module, "chrysalide_plugin_exit");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- case DPS_CORE_MANAGEMENT:
-
- switch (action)
- {
- case PGA_NATIVE_PLUGINS_LOADED:
- case PGA_ALL_PLUGINS_LOADED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded");
- break;
-
- case PGA_TYPE_BUILDING:
- valid = check_plugin_symbol(module, "chrysalide_plugin_build_type_instance");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
- break;
-
- }
-
- break;
-
-#if 0
-
- case DPC_GUI:
-
- switch (sub)
- {
- case DPS_SETUP:
-
- switch (action)
- {
- case PGA_GUI_THEME:
- valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- case DPS_RUNNING:
-
- switch (action)
- {
- case PGA_PANEL_CREATION:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_creation");
- break;
-
- case PGA_PANEL_DOCKING:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_docking");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
- break;
-
- }
-
- break;
-
- case DPC_BINARY_PROCESSING:
-
- switch (sub)
- {
- case DPS_CONTENT:
-
- switch (action)
- {
- case PGA_CONTENT_EXPLORER:
- case PGA_CONTENT_RESOLVER:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content");
- break;
-
- case PGA_CONTENT_ANALYZED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
+ result = false;
- break;
-
- case DPS_FORMAT:
+ log_variadic_message(LMT_ERROR, _("ABI mismatch detected: %08x (plugin) vs %08x (core)"),
+ plugin->abi_version, CURRENT_ABI_VERSION);
- switch (action)
- {
- case PGA_FORMAT_ANALYSIS_STARTED:
- case PGA_FORMAT_ANALYSIS_ENDED:
- case PGA_FORMAT_POST_ANALYSIS_STARTED:
- case PGA_FORMAT_POST_ANALYSIS_ENDED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis");
- break;
+ }
- case PGA_FORMAT_PRELOAD:
- valid = check_plugin_symbol(module, "chrysalide_plugin_preload_binary_format");
- break;
+ /* Mémorisation des informations */
- case PGA_FORMAT_ATTACH_DEBUG:
- valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug");
- break;
+ if (result)
+ {
+ plugin->name = strdup(name);
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
+ if (desc != NULL)
+ plugin->desc = strdup(desc);
- }
+ if (version != NULL)
+ plugin->version = strdup(version);
- break;
+ if (url != NULL)
+ plugin->url = strdup(url);
- case DPS_DISASSEMBLY:
- valid = check_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event");
- break;
-
- case DPS_DETECTION:
- valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools");
- break;
+ if (count > 0)
+ {
+ plugin->required = malloc(count * sizeof(char *));
+ plugin->required_count = 0;
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ for (i = 0; i < count; i++)
+ {
+ for (k = 0; k < plugin->required_count; k++)
+ if (strcmp(required[i], plugin->required[k]) == 0)
break;
- }
+ if (k < plugin->required_count)
+ continue;
-#endif
+ plugin->required[plugin->required_count++] = strdup(required[i]);
- break;
+ }
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
- break;
+ plugin->required = realloc(plugin->required, plugin->required_count * sizeof(char *));
}
}
- if (!valid)
- goto missing_feature;
-
- gtype = build_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name,
- (GClassInitFunc)g_plugin_module_init_gclass, module, NULL);
-
- if (gtype == G_TYPE_INVALID)
- goto no_instance;
-
- result = g_object_new(gtype, NULL);
-
- result->filename = strdup(filename);
- result->module = module;
-
- result->interface = interface;
-
- set_self(result);
-
return result;
- no_self_setter:
-
- log_variadic_message(LMT_ERROR, _("Self pointer setter is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- no_interface:
-
- log_variadic_message(LMT_ERROR, _("Main interface is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- wrong_abi:
-
- log_variadic_message(LMT_ERROR, _("ABI mismatch detected! Plugin '%s' rejected"), filename);
- goto bad_plugin;
-
- missing_feature:
-
- log_variadic_message(LMT_ERROR, _("An expected feature is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- no_instance:
-
- log_variadic_message(LMT_ERROR, _("Unabled to create an instance of plugin '%s'"), filename);
-
- bad_plugin:
-
- g_module_close(module);
-
- bad_module:
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : class = classe à initialiser. *
-* module = module représentant le greffon chargé en mémoire. *
+* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Initialise la classe des greffons d'extension. *
+* Description : Indique le nom associé à un greffon. *
* *
-* Retour : - *
+* Retour : Désignation interne de l'extension, pour référence(s). *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module)
+const char *g_plugin_module_get_name(const GPluginModule *plugin)
{
- const plugin_interface *interface; /* Déclaration d'interfaçage */
- size_t i; /* Boucle de parcours */
- uint32_t action; /* Identifiant d'une action */
- uint32_t category; /* Catégorie principale */
- uint32_t sub; /* Sous-catégorie visée */
-
-
-#undef load_plugin_symbol
-
-#define load_plugin_symbol(mod, sym, dest) \
- ({ \
- bool __result; \
- __result = g_module_symbol(mod, sym, (gpointer *)dest); \
- assert(__result); \
- __result; \
- })
-
-
- load_plugin_symbol(module, "_chrysalide_plugin", &interface);
-
- for (i = 0; i < interface->actions_count; i++)
- {
- action = interface->actions[i];
- category = MASK_PLUGIN_CATEGORY(action);
- sub = MASK_PLUGIN_SUB_CATEGORY(action);
-
- switch (category)
- {
- case DPC_BASIC:
-
- switch (sub)
- {
- case DPS_NONE:
- break;
-
- case DPS_PG_MANAGEMENT:
-
- switch (action)
- {
- case PGA_PLUGIN_INIT:
- load_plugin_symbol(module, "chrysalide_plugin_init", &class->init);
- break;
-
- case PGA_PLUGIN_LOADED:
- load_plugin_symbol(module, "chrysalide_plugin_manage", &class->manage);
- break;
-
- case PGA_PLUGIN_EXIT:
- load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_CORE_MANAGEMENT:
-
- switch (action)
- {
- case PGA_NATIVE_PLUGINS_LOADED:
- case PGA_ALL_PLUGINS_LOADED:
- load_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded",
- &class->plugins_loaded);
- break;
-
- case PGA_TYPE_BUILDING:
- load_plugin_symbol(module, "chrysalide_plugin_build_type_instance",
- &class->build_instance);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-#if 0
- case DPC_GUI:
-
- switch (sub)
- {
- case DPS_SETUP:
-
- switch (action)
- {
- case PGA_GUI_THEME:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_include_theme",
- &class->include_theme);
-#endif
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_RUNNING:
-
- switch (action)
- {
- case PGA_PANEL_CREATION:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_on_panel_creation",
- &class->notify_panel);
-#endif
- break;
-
- case PGA_PANEL_DOCKING:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_on_panel_docking",
- &class->notify_docking);
-#endif
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- default:
- assert(false);
- break;
+ const char *result; /* Valeur finale à renvoyer */
- }
+ result = plugin->name;
- break;
-
- case DPC_BINARY_PROCESSING:
-
- switch (sub)
- {
- case DPS_CONTENT:
-
- switch (action)
- {
- case PGA_CONTENT_EXPLORER:
- case PGA_CONTENT_RESOLVER:
- load_plugin_symbol(module, "chrysalide_plugin_handle_binary_content",
- &class->handle_content);
- break;
-
- case PGA_CONTENT_ANALYZED:
- load_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content",
- &class->handle_loaded);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_FORMAT:
-
- switch (action)
- {
- case PGA_FORMAT_ANALYSIS_STARTED:
- case PGA_FORMAT_ANALYSIS_ENDED:
- case PGA_FORMAT_POST_ANALYSIS_STARTED:
- case PGA_FORMAT_POST_ANALYSIS_ENDED:
- load_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis",
- &class->handle_fmt_analysis);
- break;
-
- case PGA_FORMAT_PRELOAD:
- load_plugin_symbol(module, "chrysalide_plugin_preload_binary_format", &class->preload_format);
- break;
-
- case PGA_FORMAT_ATTACH_DEBUG:
- load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug);
- break;
+ return result;
- default:
- assert(false);
- break;
+}
- }
- break;
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Fournit une description fonctionnelle d'un greffon. *
+* *
+* Retour : Description textuelle associée à une extension ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- case DPS_DISASSEMBLY:
- load_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event", &class->process_disass);
- break;
+const char *g_plugin_module_get_desc(const GPluginModule *plugin)
+{
+ const char *result; /* Valeur finale à renvoyer */
- case DPS_DETECTION:
- load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect);
- break;
+ result = plugin->desc;
- default:
- assert(false);
- break;
+ return result;
- }
+}
-#endif
- break;
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Fournit la version d'un greffon et de ses fonctionnalités. *
+* *
+* Retour : Version sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- default:
- assert(false);
- break;
+const char *g_plugin_module_get_version(const GPluginModule *plugin)
+{
+ const char *result; /* Valeur finale à renvoyer */
- }
+ result = plugin->version;
- }
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à valider. *
+* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Fournit le nom brut associé au greffon. *
+* Description : Fournit l'URL des ressources en ligne liées à un greffon. *
* *
-* Retour : Désignation brute du greffon. *
+* Retour : URL de renvoi associée à une extension ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_plugin_module_get_modname(const GPluginModule *plugin)
+const char *g_plugin_module_get_url(const GPluginModule *plugin)
{
- char *result; /* Désignation brute à renvoyer*/
- GPluginModuleClass *class; /* Classe de l'instance active */
-
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- result = class->get_modname(plugin);
+ const char *result; /* Valeur finale à renvoyer */
- /**
- * Tente une opération de la dernière chance.
- *
- * Dans le cas d'un module Python, la fonction de classe peut ne pas
- * trouver de support si l'extension Python n'est pas au point.
- */
- if (result == NULL && class->get_modname != _g_plugin_module_get_modname)
- result = _g_plugin_module_get_modname(plugin);
+ result = plugin->url;
return result;
@@ -844,41 +399,24 @@ char *g_plugin_module_get_modname(const GPluginModule *plugin)
/******************************************************************************
* *
-* Paramètres : plugin = greffon à valider. *
+* Paramètres : plugin = greffon à consulter. *
+* count = taille de la liste fournie. [OUT] *
* *
-* Description : Fournit le nom brut associé au greffon. *
+* Description : Fournit la liste des dépendances d'un greffon donné. *
* *
-* Retour : Désignation brute du greffon. *
+* Retour : Liste des noms d'extensions requises pour une extension. *
* *
* Remarques : - *
* *
******************************************************************************/
-static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
+const char * const *g_plugin_module_get_requirements(const GPluginModule *plugin, size_t *count)
{
- char *result; /* Désignation brute à renvoyer*/
- char *path; /* Chemin à traiter */
- char *filename; /* Nom de bibliothèque partagée*/
- size_t length; /* Taille du nom */
-
- path = strdup(g_plugin_module_get_filename(G_PLUGIN_MODULE(plugin)));
-
- filename = basename(path);
-
- if (strncmp(filename, "lib", 3) == 0)
- filename += 3;
-
- length = strlen(filename);
-
- if (length >= 3)
- {
- if (strncmp(&filename[length - 3], ".so", 3) == 0)
- filename[length - 3] = '\0';
- }
+ const char * const *result; /* Valeur finale à renvoyer */
- result = strdup(filename);
+ result = CONST_ARRAY_CAST(plugin->required, char);
- free(path);
+ *count = plugin->required_count;
return result;
@@ -889,7 +427,7 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
* *
* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Indique le fichier contenant le greffon manipulé. *
+* Description : Pointe le fichier contenant le greffon manipulé. *
* *
* Retour : Chemin d'accès au greffon. *
* *
@@ -897,28 +435,42 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
* *
******************************************************************************/
-const char *g_plugin_module_get_filename(const GPluginModule *plugin)
+char *g_plugin_module_get_filename(const GPluginModule *plugin)
{
- return plugin->filename;
+ char *result; /* Chemin d'accès à renvoyer */
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ result = class->get_filename(plugin);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à consulter. *
+* Paramètres : plugin = greffon à valider. *
* *
-* Description : Fournit la description du greffon dans son intégralité. *
+* Description : Fournit le nom brut associé au greffon. *
* *
-* Retour : Interfaçage renseigné. *
+* Retour : Désignation brute du greffon. *
* *
* Remarques : - *
* *
******************************************************************************/
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin)
+char *g_plugin_module_get_modname(const GPluginModule *plugin)
{
- return plugin->interface;
+ char *result; /* Désignation brute à renvoyer*/
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ result = class->get_modname(plugin);
+
+ return result;
}
@@ -979,7 +531,6 @@ void g_plugin_module_override_flags(GPluginModule *plugin, PluginStatusFlags fla
bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule **list, size_t count)
{
bool result; /* Bilan à faire remonter */
- const plugin_interface *pg_iface; /* Définition du greffon */
bitfield_t *new; /* Nouvelle définition */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
@@ -997,15 +548,13 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
if ((plugin->flags & (PSF_UNKNOW_DEP | PSF_DEP_LOOP)) == 0)
{
- pg_iface = g_plugin_module_get_interface(plugin);
-
/* Collecte des dépendances */
new = dup_bit_field(plugin->dependencies);
- for (i = 0; i < pg_iface->required_count; i++)
+ for (i = 0; i < plugin->required_count; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], &index);
+ dependency = get_plugin_by_name(plugin->required[i], &index);
if (dependency == NULL)
plugin->flags |= PSF_UNKNOW_DEP;
@@ -1015,7 +564,7 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
if (dependency->dependencies == NULL)
dependency->dependencies = create_bit_field(count, false);
- set_in_bit_field(new, index, 1);
+ set_in_bit_field(new, index);
or_bit_field(new, dependency->dependencies);
/**
@@ -1023,7 +572,7 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
*/
if (test_in_bit_field(plugin->dependencies, index))
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -1041,13 +590,14 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
/* Vérification sanitaire */
- dependency = get_plugin_by_name(pg_iface->name, &index);
+ dependency = get_plugin_by_name(plugin->name, &index);
assert(dependency != NULL);
+ assert(dependency == plugin);
if (test_in_bit_field(plugin->dependencies, index))
plugin->flags |= PSF_DEP_LOOP;
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -1075,12 +625,12 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
{
bool result; /* Bilan à retourner */
PluginStatusFlags flags; /* Fanions de greffon */
- const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
+ char *filename; /* Chemin d'accès au greffon */
GPluginModuleClass *class; /* Classe de l'instance active */
- //GGenConfig *config; /* Configuration à charger */
- char *dir; /* Répertoire modifiable */
+ char *tmp; /* Chaîne modifiable */
+ char *dir; /* Pointeur vers répertoire */
/* Si un essai précédent a déjà échoué ou réussi... */
@@ -1092,40 +642,41 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
/* Chargement des dépendances */
- pg_iface = g_plugin_module_get_interface(plugin);
-
result = true;
- for (i = 0; i < pg_iface->required_count && result; i++)
+ filename = g_plugin_module_get_filename(plugin);
+
+ for (i = 0; i < plugin->required_count && result; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+ dependency = get_plugin_by_name(plugin->required[i], NULL);
assert(dependency != NULL);
result = g_plugin_module_load(dependency, list, count);
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
if (!result)
{
- log_variadic_message(LMT_ERROR,
- _("Some dependencies failed to load for plugin '%s'"), plugin->filename);
+ log_variadic_message(LMT_ERROR, _("Some dependencies failed to load for plugin '%s'"), filename);
+
+ plugin->flags |= PSF_FAILURE;
goto failure;
+
}
/* Chargement du greffon courant */
class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- if (class->init != NULL)
+ if (class->enable != NULL)
{
- result = class->init(plugin);
+ result = class->enable(plugin);
if (!result)
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' failed to load itself..."), plugin->filename);
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' failed to load itself..."), filename);
plugin->flags |= PSF_FAILURE;
goto failure;
@@ -1134,39 +685,23 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
}
- g_plugin_module_create_config(plugin);
-
- result = g_plugin_module_manage(plugin, PGA_PLUGIN_LOADED);
-
- if (!result)
- {
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' failed to complete loading..."), plugin->filename);
-
- plugin->flags |= PSF_FAILURE;
- goto failure;
-
- }
-
- /*
- config = g_plugin_module_get_config(plugin);
- g_generic_config_read(config);
- g_object_unref(G_OBJECT(config));
- */
+ /* Message de bilan */
- dir = strdup(plugin->filename);
- dir = dirname(dir);
+ tmp = strdup(filename);
+ dir = dirname(tmp);
log_variadic_message(LMT_PROCESS,
_("Loaded the '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"),
- strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir);
+ strrchr(filename, G_DIR_SEPARATOR) + 1, dir);
- free(dir);
+ free(tmp);
plugin->flags |= PSF_LOADED;
failure:
+ free(filename);
+
return result;
}
@@ -1203,7 +738,7 @@ char *g_plugin_module_build_config_filename(const GPluginModule *plugin, const c
suffix = stradd(suffix, G_DIR_SEPARATOR_S);
suffix = stradd(suffix, final);
- result = get_xdg_config_dir(suffix);
+ result = get_xdg_config_dir(suffix, true);
free(suffix);
free(modname);
@@ -1227,31 +762,6 @@ char *g_plugin_module_build_config_filename(const GPluginModule *plugin, const c
/******************************************************************************
* *
-* Paramètres : plugin = greffon à compléter. *
-* *
-* Description : Met en place la configuration dédiée au greffon. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_plugin_module_create_config(GPluginModule *plugin)
-{
- char *filename; /* Chemin d'accès particulier */
-
- filename = g_plugin_module_build_config_filename(plugin, "config.xml", false);
-
- //plugin->config = g_generic_config_new_from_file(filename);
-
- free(filename);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : plugin = greffon à consulter. *
* *
* Description : Fournit la configuration mise en place pour le greffon. *
@@ -1295,11 +805,11 @@ void g_plugin_module_log_simple_message(const GPluginModule *plugin, LogMessageT
size_t len; /* Taille tampon disponible */
char *buffer; /* Tampon du msg reconstitué */
- len = 4 + strlen(plugin->interface->name) + 6 + strlen(msg) + 1;
+ len = 4 + strlen(plugin->name) + 6 + strlen(msg) + 1;
buffer = calloc(len, sizeof(char));
strcpy(buffer, "<i>[");
- strcat(buffer, plugin->interface->name);
+ strcat(buffer, plugin->name);
strcat(buffer, "]</i> ");
strcat(buffer, msg);
@@ -1345,80 +855,12 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
}
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* *
-* Description : Encadre une étape de la vie d'un greffon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_plugin_module_manage(GPluginModule *plugin, PluginAction action)
-{
- bool result; /* Bilan à faire remonter */
- GPluginModuleClass *class; /* Classe de l'instance active */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- bool handle_action; /* Action supportée ? */
-
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- if (class->manage == NULL)
- result = true;
-
- else
- {
- handle_action = false;
-
- pg_iface = g_plugin_module_get_interface(plugin);
-
- for (i = 0; i < pg_iface->actions_count; i++)
- if (pg_iface->actions[i] == PGA_PLUGIN_LOADED)
- {
- handle_action = true;
- break;
- }
-
- if (handle_action)
- result = class->manage(plugin/*, action*/);
- else
- result = true;
-
- }
-
- return result;
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* unused = variable non utilisé pour l'usage de __VA_ARGS__. *
-* *
-* Description : Accompagne la fin du chargement des modules. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-void g_plugin_module_notify_plugins_loaded(GPluginModule *plugin, PluginAction action, void *unused)
-{
- GPluginModuleClass *class; /* Classe de l'instance active */
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- class->plugins_loaded(plugin, action);
-}
+#if 0
/******************************************************************************
@@ -1450,8 +892,6 @@ gpointer g_plugin_module_build_type_instance(GPluginModule *plugin, PluginAction
-#if 0
-
#ifdef INCLUDE_GTK_SUPPORT
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index 5c473b2..a4cc388 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -52,6 +52,27 @@
DECLARE_GTYPE(GPluginModule, g_plugin_module, G, PLUGIN_MODULE);
+/* Indique le nom associé à un greffon. */
+const char *g_plugin_module_get_name(const GPluginModule *);
+
+/* Fournit une description fonctionnelle d'un greffon. */
+const char *g_plugin_module_get_desc(const GPluginModule *);
+
+/* Fournit la version d'un greffon et de ses fonctionnalités. */
+const char *g_plugin_module_get_version(const GPluginModule *);
+
+/* Fournit l'URL des ressources en ligne liées à un greffon. */
+const char *g_plugin_module_get_url(const GPluginModule *);
+
+/* Fournit la liste des dépendances d'un greffon donné. */
+const char * const *g_plugin_module_get_requirements(const GPluginModule *, size_t *);
+
+/* Pointe le fichier contenant le greffon manipulé. */
+char *g_plugin_module_get_filename(const GPluginModule *);
+
+/* Fournit le nom brut associé au greffon. */
+char *g_plugin_module_get_modname(const GPluginModule *);
+
/* Fanions indiquant le statut du greffon */
typedef enum _PluginStatusFlags
{
@@ -66,19 +87,6 @@ typedef enum _PluginStatusFlags
#define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE)
-
-/* Crée un module pour un greffon donné. */
-GPluginModule *g_plugin_module_new(const gchar *);
-
-/* Fournit le nom brut associé au greffon. */
-char *g_plugin_module_get_modname(const GPluginModule *);
-
-/* Indique le fichier contenant le greffon manipulé. */
-const char *g_plugin_module_get_filename(const GPluginModule *);
-
-/* Fournit la description du greffon dans son intégralité. */
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *);
-
/* Fournit des indications sur l'état du greffon. */
PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *);
@@ -103,17 +111,12 @@ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, c
/* Présente dans le journal un message complexe. */
void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType, const char *, ...);
-/* Encadre une étape de la vie d'un greffon. */
-bool g_plugin_module_manage(GPluginModule *, PluginAction);
-/* Accompagne la fin du chargement des modules natifs. */
-void g_plugin_module_notify_plugins_loaded(GPluginModule *, PluginAction, void *);
+#if 0
/* Crée une instance à partir d'un type dynamique externe. */
gpointer g_plugin_module_build_type_instance(GPluginModule *, PluginAction, GType);
-#if 0
-
#ifdef INCLUDE_GTK_SUPPORT
/* Complète une liste de resources pour thème. */
diff --git a/src/plugins/self.h b/src/plugins/self.h
index 4d5ddb0..78a3fe6 100644
--- a/src/plugins/self.h
+++ b/src/plugins/self.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * self.h - définitions pour inclusion dans les différents greffons
+ * self.h - définitions de fonctionnalités facilitant la mise en place d'extensions natives
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,72 +26,55 @@
#define _PLUGINS_SELF_H
-#ifndef _PLUGINS_PLUGIN_H
-# include "plugin.h"
-#endif
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "plugin.h"
#include "../common/compiler.h"
-/* Facilitations de déclarations */
+/* Symboles principaux */
+
+#define PLUGIN_CORE_SELF \
+static GPluginModule *_this_plugin = NULL; \
+static void chrysalide_plugin_set_self(GPluginModule *); \
+static void chrysalide_plugin_set_self(GPluginModule *plugin) \
+{ \
+ assert(_this_plugin == NULL); \
+ _this_plugin = plugin; \
+}; \
+__private GPluginModule *_chrysalide_plugin_get_self(void); \
+__private GPluginModule *_chrysalide_plugin_get_self(void) \
+{ \
+ return _this_plugin; \
+};
+
+#define NATIVE_PLUGIN_ENTRYPOINT(fc) \
+PLUGIN_CORE_SELF; \
+G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *); \
+G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *module) \
+{ \
+ GPluginModule *result; /* Instance à retourner */ \
+ result = fc(module); \
+ chrysalide_plugin_set_self(result); \
+ return result; \
+}
+
+
+/* Spécifications */
#define CHRYSALIDE_WEBSITE(p) "https://www.chrysalide.re/" p
-#define EMPTY_PG_LIST(name) \
- name = NULL, \
- name ## _count = 0 \
-
-#define BUILD_PG_LIST(name, lst) \
- name = lst, \
- name ## _count = sizeof(lst) / sizeof(lst[0]) \
-
-#define AL(...) BUILD_PG_LIST(.actions, ((plugin_action_t []){ __VA_ARGS__ }))
-
-#define RL(...) BUILD_PG_LIST(.required, ((char *[]){ __VA_ARGS__ }))
-
-#define NO_REQ EMPTY_PG_LIST(.required)
-
-
-/* Composants d'interface */
-
-#define PLUGIN_CORE_SELF \
-static GPluginModule *_this_plugin = NULL; \
-G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p); \
-G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p) { _this_plugin = p; }; \
-__private GPluginModule *_chrysalide_plugin_get_self(void); \
-__private GPluginModule *_chrysalide_plugin_get_self(void) { return _this_plugin; };
-
-#define PLUGIN_CORE_PROPS(n, d, v, u, c) \
- \
- .magic = CHRYSALIDE_PLUGIN_MAGIC, \
- .abi_version = CURRENT_ABI_VERSION, \
- \
- .gtp_name = "G" n "Plugin", \
- .name = n, \
- .desc = d, \
- .version = v, \
- .url = u, \
- \
- .container = c
-
-#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, u, r, a) \
-PLUGIN_CORE_SELF \
-G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
- PLUGIN_CORE_PROPS(n, d, v, u, false), \
- r, \
- a, \
-}
+#define NO_REQ NULL, 0
-#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, u, r, a) \
-PLUGIN_CORE_SELF \
-G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
- PLUGIN_CORE_PROPS(n, d, v, u, true), \
- r, \
- a, \
-}
+#define BUILD_PG_LIST(lst) lst, sizeof(lst) / sizeof(lst[0])
+
+#define REQ_LIST(...) BUILD_PG_LIST((const char *[]){ __VA_ARGS__ })
-/* Manipulations accélérées */
+/* Journalisation */
__private GPluginModule *_chrysalide_plugin_get_self(void);
diff --git a/src/plugins/tweakable-int.h b/src/plugins/tweakable-int.h
new file mode 100644
index 0000000..776626f
--- /dev/null
+++ b/src/plugins/tweakable-int.h
@@ -0,0 +1,50 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweakable-int.h - définitions internes propres aux participations aux mécanismes de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_TWEAKABLE_INT_H
+#define _PLUGINS_TWEAKABLE_INT_H
+
+
+#include "tweakable.h"
+
+
+
+/* ------------------- INTEGRATION DANS L'EDITION DES PREFERENCES ------------------- */
+
+
+/* Fournit une liste de sections de configuration. */
+typedef tweak_info_t * (* get_tweakable_plugin_info) (const GTweakablePlugin *, size_t *);
+
+
+/* Greffon avec des compléments pour l'interface de configuration (interface) */
+struct _GTweakablePluginInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ get_tweakable_plugin_info get_info; /* Récupération de section(s) */
+
+};
+
+
+
+#endif /* _PLUGINS_TWEAKABLE_INT_H */
diff --git a/src/plugins/tweakable.c b/src/plugins/tweakable.c
new file mode 100644
index 0000000..517c4a3
--- /dev/null
+++ b/src/plugins/tweakable.c
@@ -0,0 +1,98 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweakable.c - participation aux mécanismes de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tweakable.h"
+
+
+#include "tweakable-int.h"
+
+
+
+/* ------------------- INTEGRATION DANS L'EDITION DES PREFERENCES ------------------- */
+
+
+/* Procède à l'initialisation de l'interface d'intervention. */
+static void g_tweakable_plugin_default_init(GTweakablePluginInterface *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTEGRATION DANS L'EDITION DES PREFERENCES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type d'une interface pour l'intervention dans la gestion des greffons. */
+G_DEFINE_INTERFACE(GTweakablePlugin, g_tweakable_plugin, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'intervention. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_tweakable_plugin_default_init(GTweakablePluginInterface *iface)
+{
+ iface->get_info = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = interface à manipuler. *
+* count = taille de la liste renvoyée. [OUT] *
+* *
+* Description : Fournit une liste de sections de configuration. *
+* *
+* Retour : Définition(s) de section de configuration ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+tweak_info_t *g_tweakable_plugin_get_tweak_info(const GTweakablePlugin *plugin, size_t *count)
+{
+ tweak_info_t *result; /* Liste à renvoyer */
+ GTweakablePluginInterface *iface; /* Interface utilisée */
+
+ iface = G_TWEAKABLE_PLUGIN_GET_IFACE(plugin);
+
+ if (iface->get_info != NULL)
+ result = iface->get_info(plugin, count);
+
+ else
+ {
+ *count = 0;
+ result = NULL;
+ }
+
+ return result;
+
+}
diff --git a/src/plugins/tweakable.h b/src/plugins/tweakable.h
new file mode 100644
index 0000000..aea70b4
--- /dev/null
+++ b/src/plugins/tweakable.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweakable.h - prototypes pour la participation aux mécanismes de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_TWEAKABLE_H
+#define _PLUGINS_TWEAKABLE_H
+
+
+#include "../glibext/helpers.h"
+#include "../gtkext/tweak.h"
+
+
+
+/* ------------------- INTEGRATION DANS L'EDITION DES PREFERENCES ------------------- */
+
+
+#define G_TYPE_TWEAKABLE_PLUGIN (g_tweakable_plugin_get_type())
+
+DECLARE_INTERFACE(GTweakablePlugin, g_tweakable_plugin, G, TWEAKABLE_PLUGIN);
+
+
+/* Fournit une liste de sections de configuration. */
+tweak_info_t *g_tweakable_plugin_get_tweak_info(const GTweakablePlugin *, size_t *);
+
+
+
+/* -------------------- SOLLICITATION DES FONCTIONNALITES CREEES -------------------- */
+
+
+#define get_tweakable_plugins_info(c) \
+ ({ \
+ tweak_info_t *__all_info; \
+ __all_info = accumulate_from_all_plugins(G_TYPE_TWEAKABLE_PLUGIN, \
+ G_TWEAKABLE_PLUGIN, \
+ g_tweakable_plugin_get_tweak_info, \
+ tweak_info_t, \
+ c); \
+ __all_info; \
+ })
+
+
+
+#endif /* _PLUGINS_TWEAKABLE_H */
diff --git a/src/rost.c b/src/rost.c
index 4a052c3..b94b367 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -41,7 +41,9 @@
#include "analysis/scan/scanner.h"
#include "analysis/scan/patterns/backends/acism.h"
#include "analysis/scan/patterns/backends/bitap.h"
-#include "analysis/scan/patterns/backends/hyperscan.h"
+#ifdef INCLUDE_HS_SUPPORT
+# include "analysis/scan/patterns/backends/hyperscan.h"
+#endif
#include "core/core.h"
#include "core/global.h"
#include "core/logs.h"
@@ -93,7 +95,11 @@ static void show_rost_help(const char *name)
printf("\n");
+#ifdef INCLUDE_HS_SUPPORT
printf("\t-A --algorithm=NAME\tSelect one of the available algorithms for data: acism, bitmap, hyperscan (default: acsim).\n");
+#else
+ printf("\t-A --algorithm=NAME\tSelect one of the available algorithms for data: acism, bitmap (default: acsim).\n");
+#endif
printf("\t-C --check-only\t\tValidate the rule syntax without performing a scan (discard the file/dir argument).\n");
printf("\t-j --print-json\t\tPrint matching strings in JSON format instead of simple text.\n");
printf("\t-s --print-strings\tPrint matching strings (default text format only).\n");
@@ -303,8 +309,10 @@ int main(int argc, char **argv)
g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND);
else if (strcmp(optarg, "bitmap") == 0)
g_scan_options_set_backend_for_data(options, G_TYPE_BITAP_BACKEND);
+#ifdef INCLUDE_HS_SUPPORT
else if (strcmp(optarg, "hyperscan") == 0)
g_scan_options_set_backend_for_data(options, G_TYPE_HYPERSCAN_BACKEND);
+#endif
else
g_scan_options_set_backend_for_data(options, G_TYPE_INVALID);
break;
diff --git a/src/schemas/re.chrysalide.framework.gschema.xml b/src/schemas/re.chrysalide.framework.gschema.xml
index 4a16f12..534f735 100644
--- a/src/schemas/re.chrysalide.framework.gschema.xml
+++ b/src/schemas/re.chrysalide.framework.gschema.xml
@@ -1,19 +1,106 @@
<schemalist gettext-domain="chrysalide">
- <schema id="re.chrysalide.framework" path="/re/chrysalide/framework/">
- <child schema="re.chrysalide.framework.mainapp" name="mainapp"/>
- </schema>
-
- <schema id="re.chrysalide.framework.mainapp" path="/re/chrysalide/framework/mainapp/">
- <key name="window-width" type="i">
- <default>600</default>
- </key>
- <key name="window-height" type="i">
- <default>400</default>
- </key>
- <key name="window-maximized" type="b">
- <default>false</default>
- </key>
- </schema>
+ <schema id="re.chrysalide.framework" path="/re/chrysalide/framework/">
+ <child schema="re.chrysalide.framework.paths" name="paths"/>
+ <child schema="re.chrysalide.framework.gui" name="gui"/>
+ <child schema="re.chrysalide.framework.tiledgrid" name="tiles"/>
+ <child schema="re.chrysalide.framework.secstorage" name="secstorage"/>
+ </schema>
+
+ <schema id="re.chrysalide.framework.paths" path="/re/chrysalide/framework/paths/">
+ <key name="tmp-work-dir" type="s">
+ <default>"/tmp/chrysalide"</default>
+ <summary>Directory for temporary contents</summary>
+ <description>
+ Location of files created as cache and meant to get deleted when unused
+ </description>
+ </key>
+ </schema>
+
+ <schema id="re.chrysalide.framework.gui" path="/re/chrysalide/framework/gui/">
+ <key name="window-width" type="i">
+ <default>600</default>
+ </key>
+ <key name="window-height" type="i">
+ <default>400</default>
+ </key>
+ <key name="window-maximized" type="b">
+ <default>false</default>
+ </key>
+ </schema>
+
+ <flags id="re.chrysalide.framework.tiledgrid.LayoutReachOptions">
+ <value nick="left-top-reach" value="1"/>
+ <value nick="left-bottom-reach" value="2"/>
+ <value nick="right-top-reach" value="4"/>
+ <value nick="right-bottom-reach" value="8"/>
+ </flags>
+
+ <schema id="re.chrysalide.framework.tiledgrid">
+
+ <key name="layout" flags="re.chrysalide.framework.tiledgrid.LayoutReachOptions">
+ <default>["left-top-reach","right-top-reach"]</default>
+ <summary>Main panel layout</summary>
+ <description>Layout details describing the border panel locations</description>
+ </key>
+
+ <key name="top-visibility" type="b">
+ <default>false</default>
+ <summary>Top panel visibility</summary>
+ <description>Visbility of the panel located at the top of a tiling grid</description>
+ </key>
+
+ <key name="top-request" type="u">
+ <default>300</default>
+ <summary>Top panel height</summary>
+ <description>Height request for the panel located at the top of a tiling grid</description>
+ </key>
+
+ <key name="left-visibility" type="b">
+ <default>false</default>
+ <summary>Left panel visibility</summary>
+ <description>Visbility of the panel located at the left of a tiling grid</description>
+ </key>
+
+ <key name="left-request" type="u">
+ <default>300</default>
+ <summary>Left panel height</summary>
+ <description>Width request for the panel located at the left of a tiling grid</description>
+ </key>
+
+ <key name="right-visibility" type="b">
+ <default>false</default>
+ <summary>Right panel visibility</summary>
+ <description>Visbility of the panel located at the right of a tiling grid</description>
+ </key>
+
+ <key name="right-request" type="u">
+ <default>300</default>
+ <summary>Right panel height</summary>
+ <description>Width request for the panel located at the right of a tiling grid</description>
+ </key>
+
+ <key name="bottom-visibility" type="b">
+ <default>false</default>
+ <summary>Bottom panel visibility</summary>
+ <description>Visbility of the panel located at the bottom of a tiling grid</description>
+ </key>
+
+ <key name="bottom-request" type="u">
+ <default>250</default>
+ <summary>Bottom panel height</summary>
+ <description>Height request for the panel located at the bottom of a tiling grid</description>
+ </key>
+
+ </schema>
+
+ <schema id="re.chrysalide.framework.secstorage" path="/re/chrysalide/framework/secstorage/">
+ <key name="salt" type="ay">
+ <default>[]</default>
+ </key>
+ <key name="master" type="ay">
+ <default>[]</default>
+ </key>
+ </schema>
</schemalist>