From 0daed1fa6212eb83b65ccd10c9f2c80bf12c6d27 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 13 Aug 2021 00:00:35 +0200
Subject: Connect a factory for operands to all the instructions.

---
 src/arch/instruction.c | 13 ++++++++-
 src/core/core.c        |  3 +++
 src/core/processors.c  | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/core/processors.h  | 10 +++++++
 4 files changed, 97 insertions(+), 1 deletion(-)

diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 4079e82..cd9ccff 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -35,6 +35,7 @@
 #include "instruction-int.h"
 #include "storage.h"
 #include "../core/logs.h"
+#include "../core/processors.h"
 #include "../glibext/gbinarycursor.h"
 #include "../glibext/linegen-int.h"
 #include "../gtkext/gtkblockdisplay.h"
@@ -666,9 +667,19 @@ void g_arch_instruction_unlock_operands(GArchInstruction *instr)
 
 void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand)
 {
+    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, &operand, sizeof(GArchOperand *));
+    add_item_to_flat_array(&instr->operands, &singleton, sizeof(GArchOperand *));
 
     g_arch_instruction_unlock_operands(instr);
 
diff --git a/src/core/core.c b/src/core/core.c
index a72122c..62f6821 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -106,6 +106,7 @@ bool load_all_core_components(bool cs)
             if (result) result = init_segment_content_hash_table();
 
             register_arch_gtypes();
+            init_operands_factory();
 
             if (result) result = init_chrysalide_dynamic_types();
 
@@ -136,6 +137,8 @@ void unload_all_core_components(bool cs)
     {
         exit_chrysalide_dynamic_types();
 
+        exit_operands_factory();
+
         unload_demanglers_definitions();
 
         unload_processors_definitions();
diff --git a/src/core/processors.c b/src/core/processors.c
index 3211009..666ddac 100644
--- a/src/core/processors.c
+++ b/src/core/processors.c
@@ -24,6 +24,7 @@
 #include "processors.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <pthread.h>
 #include <string.h>
@@ -37,6 +38,9 @@
 
 
 
+/* Cache des singletons d'opérandes */
+static GSingletonFactory *__operands_factory = NULL;
+
 /* Caractéristiques d'un processeur */
 typedef struct _proc_t
 {
@@ -85,6 +89,74 @@ void register_arch_gtypes(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Met en place le fournisseur d'instances uniques d'opérandes. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_operands_factory(void)
+{
+    assert(__operands_factory == NULL);
+
+    __operands_factory = g_singleton_factory_new();
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit l'usine à opérandes pour toutes les instructions.    *
+*                                                                             *
+*  Retour      : Producteur d'instances uniques.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GSingletonFactory *get_operands_factory(void)
+{
+    GSingletonFactory *result;              /* Usine à renvoyer            */
+
+    result = __operands_factory;
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Supprime le fournisseur d'instances uniques d'opérandes.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_operands_factory(void)
+{
+    assert(__operands_factory != NULL);
+
+    g_clear_object(&__operands_factory);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : type = type GLib représentant le type à instancier.          *
 *                                                                             *
 *  Description : Enregistre un processeur pour une architecture donnée.       *
diff --git a/src/core/processors.h b/src/core/processors.h
index f95c6c2..6aa2d1e 100644
--- a/src/core/processors.h
+++ b/src/core/processors.h
@@ -30,12 +30,22 @@
 
 
 #include "../arch/processor.h"
+#include "../glibext/singleton.h"
 
 
 
 /* Assure l'enregistrement de types pour les caches à charger. */
 void register_arch_gtypes(void);
 
+/* Met en place le fournisseur d'instances uniques d'opérandes. */
+void init_operands_factory(void);
+
+/* Fournit l'usine à opérandes pour toutes les instructions. */
+GSingletonFactory *get_operands_factory(void);
+
+/* Supprime le fournisseur d'instances uniques d'opérandes. */
+void exit_operands_factory(void);
+
 /* Enregistre un processeur pour une architecture donnée. */
 bool register_processor_type(GType);
 
-- 
cgit v0.11.2-87-g4458