From ebfc6a8ebcef2b42beb6ef12e4946bb2f73f2723 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 6 Aug 2018 19:08:01 +0200
Subject: Secured the links between instructions.

---
 src/arch/instruction.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/arch/instruction.h |   3 ++
 2 files changed, 126 insertions(+)

diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 1bf3c9b..5ce0c12 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -208,6 +208,18 @@ static void g_arch_instruction_dispose(GArchInstruction *instr)
 
     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_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
 
 }
@@ -791,11 +803,15 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
     new_src.linked = instr;
     new_src.type = type;
 
+    ref_instr_link((&new_src));
+
     /* Côté point de départ */
 
     new_dst.linked = dest;
     new_dst.type = type;
 
+    ref_instr_link((&new_dst));
+
     /* Ajout dans le respect d'une cohérence globale */
 
     g_arch_instruction_lock_src(dest);
@@ -898,6 +914,113 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr = instruction dont les informations sont à traiter.    *
+*                                                                             *
+*  Description : Supprime tous les liens établis avec d'autres instructions.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+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         */
+
+    /* Coté sources */
+
+    g_arch_instruction_lock_src(instr);
+
+    while (count_flat_array_items(instr->from) > 0)
+    {
+        link_src = get_flat_array_item(instr->from, 0, sizeof(instr_link_t));
+
+        other = link_src->linked;
+
+        g_arch_instruction_lock_dest(other);
+
+        count = count_flat_array_items(other->to);
+
+        for (i = 0; i < count; i++)
+        {
+            link_dst = get_flat_array_item(other->to, i, sizeof(instr_link_t));
+
+            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));
+
+    }
+
+    g_arch_instruction_unlock_src(instr);
+
+    /* Coté destinations */
+
+    g_arch_instruction_lock_dest(instr);
+
+    while (count_flat_array_items(instr->to) > 0)
+    {
+        link_dst = get_flat_array_item(instr->to, 0, sizeof(instr_link_t));
+
+        other = link_dst->linked;
+
+        g_arch_instruction_lock_src(other);
+
+        count = count_flat_array_items(other->from);
+
+        for (i = 0; i < count; i++)
+        {
+            link_src = get_flat_array_item(other->from, i, sizeof(instr_link_t));
+
+            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;
+
+            }
+
+        }
+
+        assert(i < count);
+
+        g_arch_instruction_unlock_src(other);
+
+        unref_instr_link(link_dst);
+
+        rem_item_from_flat_array(&instr->to, 0, sizeof(instr_link_t));
+
+    }
+
+    g_arch_instruction_unlock_dest(instr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr = instruction dont les informations sont à consulter.  *
 *                                                                             *
 *  Description : Fournit la quantité d'instructions pointant vers une autre.  *
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 0c8510a..8289a43 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -227,6 +227,9 @@ void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, Instru
 /* Change la nature d'un lien entre deux instructions. */
 bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
 
+/* 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)
 
-- 
cgit v0.11.2-87-g4458