From 7f35f8d2f211fdf087252ede7665e9c81f35cdc7 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 27 Jan 2013 00:43:59 +0000
Subject: Implemented the first steps for visiting or replacing items in
 decompiled instructions.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@331 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                    |  17 +++++++
 src/decomp/expr/access.c     |  84 +++++++++++++++++++++++++++++++++
 src/decomp/expr/arithm.c     |  84 +++++++++++++++++++++++++++++++++
 src/decomp/expr/array.c      |  84 +++++++++++++++++++++++++++++++++
 src/decomp/expr/assign.c     |  84 +++++++++++++++++++++++++++++++++
 src/decomp/expr/block.c      |  80 ++++++++++++++++++++++++++++++++
 src/decomp/expr/call.c       |  80 ++++++++++++++++++++++++++++++++
 src/decomp/expr/cond.c       |  84 +++++++++++++++++++++++++++++++++
 src/decomp/expr/return.c     |  78 +++++++++++++++++++++++++++++++
 src/decomp/instr/ite.c       | 107 +++++++++++++++++++++++++++++++++++--------
 src/decomp/instruction-int.h |   6 ++-
 src/decomp/instruction.c     |  58 ++++++++++++++++++-----
 src/decomp/instruction.h     |  16 +++++--
 13 files changed, 827 insertions(+), 35 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b43e967..a839cc1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+13-01-27  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/decomp/expr/access.c:
+	* src/decomp/expr/arithm.c:
+	* src/decomp/expr/array.c:
+	* src/decomp/expr/assign.c:
+	* src/decomp/expr/block.c:
+	* src/decomp/expr/call.c:
+	* src/decomp/expr/cond.c:
+	* src/decomp/expr/return.c:
+	* src/decomp/instr/ite.c:
+	* src/decomp/instruction.c:
+	* src/decomp/instruction.h:
+	* src/decomp/instruction-int.h:
+	Implement the first steps for visiting or replacing items in decompiled
+	instructions.
+
 13-01-26  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/src/decomp/expr/access.c b/src/decomp/expr/access.c
index 277209a..f06c47b 100644
--- a/src/decomp/expr/access.c
+++ b/src/decomp/expr/access.c
@@ -54,6 +54,12 @@ static void g_access_expression_class_init(GAccessExpressionClass *);
 /* Initialise une instance d'accessation quelconque. */
 static void g_access_expression_init(GAccessExpression *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_access_expression_visit(GAccessExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_access_expression_replace(GAccessExpression *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_access_expression_print(const GAccessExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -99,6 +105,8 @@ static void g_access_expression_init(GAccessExpression *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_access_expression_visit;
+    instr->replace = (dec_instr_replace_fc)g_access_expression_replace;
     instr->print = (dec_instr_print_fc)g_access_expression_print;
 
 }
@@ -133,6 +141,82 @@ GDecInstruction *g_access_expression_new(GDecExpression *owner, GDecExpression *
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : expr     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_access_expression_visit(GAccessExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->owner), callback, flags, data);
+
+    if (result)
+        result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->target), callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_access_expression_replace(GAccessExpression *expr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->owner == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->owner));
+        g_object_ref(G_OBJECT(new));
+        expr->owner = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->owner), old, new);
+
+    if (expr->target == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->target));
+        g_object_ref(G_OBJECT(new));
+        expr->target = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->target), old, new);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/arithm.c b/src/decomp/expr/arithm.c
index d91e080..3811cf4 100644
--- a/src/decomp/expr/arithm.c
+++ b/src/decomp/expr/arithm.c
@@ -56,6 +56,12 @@ static void g_arithm_expression_class_init(GArithmExpressionClass *);
 /* Initialise une instance d'opération arithmétique définie. */
 static void g_arithm_expression_init(GArithmExpression *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_arithm_expression_visit(GArithmExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_arithm_expression_replace(GArithmExpression *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_arithm_expression_print(const GArithmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -101,6 +107,8 @@ static void g_arithm_expression_init(GArithmExpression *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_arithm_expression_visit;
+    instr->replace = (dec_instr_replace_fc)g_arithm_expression_replace;
     instr->print = (dec_instr_print_fc)g_arithm_expression_print;
 
 }
@@ -138,6 +146,82 @@ GDecInstruction *g_arithm_expression_new(GDecExpression *op1, ArithmOperationTyp
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : expr     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arithm_expression_visit(GArithmExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->op1), callback, flags, data);
+
+    if (result)
+        result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->op2), callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arithm_expression_replace(GArithmExpression *expr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->op1 == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->op1));
+        g_object_ref(G_OBJECT(new));
+        expr->op1 = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->op1), old, new);
+
+    if (expr->op2 == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->op2));
+        g_object_ref(G_OBJECT(new));
+        expr->op2 = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->op2), old, new);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/array.c b/src/decomp/expr/array.c
index dc487ee..4053169 100644
--- a/src/decomp/expr/array.c
+++ b/src/decomp/expr/array.c
@@ -54,6 +54,12 @@ static void g_array_access_class_init(GArrayAccessClass *);
 /* Initialise une instance d'accès à une cellule de tableau. */
 static void g_array_access_init(GArrayAccess *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_array_access_visit(GArrayAccess *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_array_access_replace(GArrayAccess *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_array_access_print(const GArrayAccess *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -99,6 +105,8 @@ static void g_array_access_init(GArrayAccess *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_array_access_visit;
+    instr->replace = (dec_instr_replace_fc)g_array_access_replace;
     instr->print = (dec_instr_print_fc)g_array_access_print;
 
 }
@@ -133,6 +141,82 @@ GDecInstruction *g_array_access_new(GDecExpression *array, GDecExpression *index
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : expr     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_array_access_visit(GArrayAccess *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->array), callback, flags, data);
+
+    if (result)
+        result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->index), callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_array_access_replace(GArrayAccess *expr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->array == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->array));
+        g_object_ref(G_OBJECT(new));
+        expr->array = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->array), old, new);
+
+    if (expr->index == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->index));
+        g_object_ref(G_OBJECT(new));
+        expr->index = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->index), old, new);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/assign.c b/src/decomp/expr/assign.c
index fd86021..26d31f6 100644
--- a/src/decomp/expr/assign.c
+++ b/src/decomp/expr/assign.c
@@ -54,6 +54,12 @@ static void g_assign_expression_class_init(GAssignExpressionClass *);
 /* Initialise une instance d'assignation quelconque. */
 static void g_assign_expression_init(GAssignExpression *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_assign_expression_visit(GAssignExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_assign_expression_replace(GAssignExpression *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_assign_expression_print(const GAssignExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -99,6 +105,8 @@ static void g_assign_expression_init(GAssignExpression *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_assign_expression_visit;
+    instr->replace = (dec_instr_replace_fc)g_assign_expression_replace;
     instr->print = (dec_instr_print_fc)g_assign_expression_print;
 
 }
@@ -133,6 +141,82 @@ GDecInstruction *g_assign_expression_new(GDecExpression *dest, GDecExpression *s
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : expr     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_assign_expression_visit(GAssignExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->dest), callback, flags, data);
+
+    if (result)
+        result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->src), callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_assign_expression_replace(GAssignExpression *expr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->dest == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->dest));
+        g_object_ref(G_OBJECT(new));
+        expr->dest = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->dest), old, new);
+
+    if (expr->src == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->src));
+        g_object_ref(G_OBJECT(new));
+        expr->src = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->src), old, new);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/block.c b/src/decomp/expr/block.c
index 5124204..3c56ef6 100644
--- a/src/decomp/expr/block.c
+++ b/src/decomp/expr/block.c
@@ -57,6 +57,12 @@ static void g_expr_block_class_init(GExprBlockClass *);
 /* Initialise une instance d'ensemble d'instructions. */
 static void g_expr_block_init(GExprBlock *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_expr_block_visit(GExprBlock *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_expr_block_replace(GExprBlock *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_expr_block_print(const GExprBlock *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -102,6 +108,8 @@ static void g_expr_block_init(GExprBlock *block)
 
     instr = G_DEC_INSTRUCTION(block);
 
+    instr->visit = (dec_instr_visit_fc)g_expr_block_visit;
+    instr->replace = (dec_instr_replace_fc)g_expr_block_replace;
     instr->print = (dec_instr_print_fc)g_expr_block_print;
 
 }
@@ -134,6 +142,78 @@ GDecInstruction *g_expr_block_new(GDecInstruction *item)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block    = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_expr_block_visit(GExprBlock *block, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < block->count && result; i++)
+        result = g_dec_instruction_visit(block->list[i], callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = première instruction à venir ausculter.              *
+*                old   = instruction décompilée à venir remplacer.            *
+*                new   = instruction décompilée à utiliser dorénavant.        *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_expr_block_replace(GExprBlock *block, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = false;
+
+    for (i = 0; i < block->count; i++)
+    {
+        if (block->list[i] == old)
+        {
+            g_object_unref(G_OBJECT(block->list[i]));
+            g_object_ref(G_OBJECT(new));
+            block->list[i] = new;
+
+            result = true;
+
+        }
+        else
+            result |= g_dec_instruction_replace(block->list[i], old, new);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block  = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/call.c b/src/decomp/expr/call.c
index e518c6f..ed1c43a 100644
--- a/src/decomp/expr/call.c
+++ b/src/decomp/expr/call.c
@@ -60,6 +60,12 @@ static void g_routine_call_class_init(GRoutineCallClass *);
 /* Initialise une instance d'appel à une routine quelconque. */
 static void g_routine_call_init(GRoutineCall *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_routine_call_visit(GRoutineCall *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_routine_call_replace(GRoutineCall *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_routine_call_print(const GRoutineCall *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -105,6 +111,8 @@ static void g_routine_call_init(GRoutineCall *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_routine_call_visit;
+    instr->replace = (dec_instr_replace_fc)g_routine_call_replace;
     instr->print = (dec_instr_print_fc)g_routine_call_print;
 
 }
@@ -137,6 +145,78 @@ GDecInstruction *g_routine_call_new(GBinRoutine *routine)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : call     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_routine_call_visit(GRoutineCall *call, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < call->count && result; i++)
+        result = g_dec_instruction_visit(call->args[i], callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : call = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_routine_call_replace(GRoutineCall *call, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = false;
+
+    for (i = 0; i < call->count; i++)
+    {
+        if (call->args[i] == old)
+        {
+            g_object_unref(G_OBJECT(call->args[i]));
+            g_object_ref(G_OBJECT(new));
+            call->args[i] = new;
+
+            result = true;
+
+        }
+        else
+            result |= g_dec_instruction_replace(call->args[i], old, new);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : call   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/cond.c b/src/decomp/expr/cond.c
index 4a9b63b..d96f483 100644
--- a/src/decomp/expr/cond.c
+++ b/src/decomp/expr/cond.c
@@ -55,6 +55,12 @@ static void g_cond_expression_class_init(GCondExpressionClass *);
 /* Initialise une instance de condition binaire quelconque. */
 static void g_cond_expression_init(GCondExpression *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_cond_expression_visit(GCondExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_cond_expression_replace(GCondExpression *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -100,6 +106,8 @@ static void g_cond_expression_init(GCondExpression *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_cond_expression_visit;
+    instr->replace = (dec_instr_replace_fc)g_cond_expression_replace;
     instr->print = (dec_instr_print_fc)g_cond_expression_print;
 
 }
@@ -136,6 +144,82 @@ GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDe
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : expr     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_cond_expression_visit(GCondExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->a), callback, flags, data);
+
+    if (result)
+        result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->b), callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_cond_expression_replace(GCondExpression *expr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->a == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->a));
+        g_object_ref(G_OBJECT(new));
+        expr->a = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->a), old, new);
+
+    if (expr->b == G_DEC_EXPRESSION(old))
+    {
+        g_object_unref(G_OBJECT(expr->b));
+        g_object_ref(G_OBJECT(new));
+        expr->b = G_DEC_EXPRESSION(new);
+
+        result = true;
+
+    }
+    else
+        result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->b), old, new);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/expr/return.c b/src/decomp/expr/return.c
index a9c10d9..d012893 100644
--- a/src/decomp/expr/return.c
+++ b/src/decomp/expr/return.c
@@ -53,6 +53,12 @@ static void g_return_expression_class_init(GReturnExpressionClass *);
 /* Initialise une instance d'ordre de retour. */
 static void g_return_expression_init(GReturnExpression *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_return_expression_visit(GReturnExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_return_expression_replace(GReturnExpression *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_return_expression_print(const GReturnExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -98,6 +104,8 @@ static void g_return_expression_init(GReturnExpression *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_return_expression_visit;
+    instr->replace = (dec_instr_replace_fc)g_return_expression_replace;
     instr->print = (dec_instr_print_fc)g_return_expression_print;
 
 }
@@ -130,6 +138,76 @@ GDecInstruction *g_return_expression_new(GDecExpression *payload)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : expr     = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_return_expression_visit(GReturnExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->payload)
+        result = g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->payload), callback, flags, data);
+    else
+        result = false;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première instruction à venir ausculter.               *
+*                old  = instruction décompilée à venir remplacer.             *
+*                new  = instruction décompilée à utiliser dorénavant.         *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_return_expression_replace(GReturnExpression *expr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (expr->payload)
+    {
+        if (expr->payload == G_DEC_EXPRESSION(old))
+        {
+            g_object_unref(G_OBJECT(expr->payload));
+            g_object_ref(G_OBJECT(new));
+            expr->payload = G_DEC_EXPRESSION(new);
+
+            result = true;
+
+        }
+        else
+            result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->payload), old, new);
+
+    }
+    else
+        result = false;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = expression à transcrire en version humaine.         *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c
index c12d314..1abf61c 100644
--- a/src/decomp/instr/ite.c
+++ b/src/decomp/instr/ite.c
@@ -72,6 +72,12 @@ static void g_ite_instruction_class_init(GITEInstructionClass *);
 /* Initialise une instance d'aiguillage du flux d'exécution. */
 static void g_ite_instruction_init(GITEInstruction *);
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_ite_instruction_visit(GITEInstruction *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_ite_instruction_replace(GITEInstruction *, GDecInstruction *, GDecInstruction *);
+
 /* Imprime pour l'écran un version humaine d'une instruction. */
 static GBufferLine *g_ite_instruction_print(const GITEInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
@@ -117,6 +123,8 @@ static void g_ite_instruction_init(GITEInstruction *expr)
 
     instr = G_DEC_INSTRUCTION(expr);
 
+    instr->visit = (dec_instr_visit_fc)g_ite_instruction_visit;
+    instr->replace = (dec_instr_replace_fc)g_ite_instruction_replace;
     instr->print = (dec_instr_print_fc)g_ite_instruction_print;
 
 }
@@ -153,34 +161,62 @@ GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmp
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : cond         = expression fixant le choix de l'aiguillage.   *
-*                true_branch  = instructions si la condition est vérifiée.    *
-*                false_branch = instructions si la cond. n'est pas vérifiée.  *
+*  Paramètres  : instr    = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
 *                                                                             *
-*  Description : Détermine le corps des différentes branches possibles.       *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_ite_instruction_set_branches(GITEInstruction *expr, GDecInstruction *true_branch, GDecInstruction *false_branch)
+static bool g_ite_instruction_visit(GITEInstruction *instr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
 {
+    bool result;                            /* Bilan à retourner           */
 
-    if (true_branch == NULL)
-    {
-        expr->inverse = true;
+    result = g_dec_instruction_visit(G_DEC_INSTRUCTION(instr->cond), callback, flags, data);
 
-        expr->true_branch = false_branch;
-        expr->false_branch = true_branch;
+    if (result)
+        result = g_dec_instruction_visit(instr->true_branch, callback, flags, data);
 
-    }
-    else
-    {
-        expr->true_branch = true_branch;
-        expr->false_branch = false_branch;
-    }
+    if (result && instr->false_branch != NULL)
+        result = g_dec_instruction_visit(instr->false_branch, callback, flags, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = première instruction à venir ausculter.              *
+*                old   = instruction décompilée à venir remplacer.            *
+*                new   = instruction décompilée à utiliser dorénavant.        *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_ite_instruction_replace(GITEInstruction *instr, GDecInstruction *old, GDecInstruction *new)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_dec_instruction_replace(G_DEC_INSTRUCTION(instr->cond), old, new);
+
+    result |= g_dec_instruction_replace(instr->true_branch, old, new);
+
+    if (instr->false_branch != NULL)
+        result |= g_dec_instruction_replace(instr->false_branch, old, new);
+
+    return result;
 
 }
 
@@ -212,8 +248,7 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBu
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond),
                                      buffer, line, output);
 
-    if (expr->true_branch != NULL)
-        result = g_dec_instruction_print(expr->true_branch, buffer, result, output);
+    result = g_dec_instruction_print(expr->true_branch, buffer, result, output);
 
     if (expr->false_branch != NULL)
     {
@@ -224,3 +259,37 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBu
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cond         = expression fixant le choix de l'aiguillage.   *
+*                true_branch  = instructions si la condition est vérifiée.    *
+*                false_branch = instructions si la cond. n'est pas vérifiée.  *
+*                                                                             *
+*  Description : Détermine le corps des différentes branches possibles.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_ite_instruction_set_branches(GITEInstruction *expr, GDecInstruction *true_branch, GDecInstruction *false_branch)
+{
+
+    if (true_branch == NULL)
+    {
+        expr->inverse = true;
+
+        expr->true_branch = false_branch;
+        expr->false_branch = true_branch;
+
+    }
+    else
+    {
+        expr->true_branch = true_branch;
+        expr->false_branch = false_branch;
+    }
+
+}
diff --git a/src/decomp/instruction-int.h b/src/decomp/instruction-int.h
index 9b29162..f0c503b 100644
--- a/src/decomp/instruction-int.h
+++ b/src/decomp/instruction-int.h
@@ -32,7 +32,10 @@
 
 
 /* Visite un ensemble hiérarchique d'instructions décompilées. */
-typedef void (* dec_instr_visit_fc) (GDecInstruction *, process_decomp_fc, void *, bool);
+typedef bool (* dec_instr_visit_fc) (GDecInstruction *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+typedef bool (* dec_instr_replace_fc) (GDecInstruction *, GDecInstruction *, GDecInstruction *);
 
 /* Imprime pour l'écran un version humaine d'une instruction. */
 typedef GBufferLine * (* dec_instr_print_fc) (const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
@@ -48,6 +51,7 @@ struct _GDecInstruction
     vmpa_t address;                         /* Position associée           */
 
     dec_instr_visit_fc visit;               /* Visite des instructions     */
+    dec_instr_replace_fc replace;           /* Remplacement à la volée     */
     dec_instr_print_fc print;               /* Impression pour à l'écran   */
 
 };
diff --git a/src/decomp/instruction.c b/src/decomp/instruction.c
index 2d42e71..3a9917a 100644
--- a/src/decomp/instruction.c
+++ b/src/decomp/instruction.c
@@ -79,29 +79,63 @@ static void g_dec_instruction_init(GDecInstruction *instr)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : instr   = première instruction à venir visiter.              *
-*                process = procédure à appeler à chaque instruction visitée.  *
-*                data    = données quelconques associées au visiteur.         *
-*                order   = précise le sens de la visite.                      *
+*  Paramètres  : instr    = première instruction à venir visiter.             *
+*                callback = procédure à appeler à chaque instruction visitée. *
+*                flags    = moments des appels à réaliser en retour.          *
+*                data     = données quelconques associées au visiteur.        *
 *                                                                             *
 *  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_dec_instruction_visit(GDecInstruction *instr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (flags & DVF_ENTER)
+        result = callback(instr, DVF_ENTER, data);
+
+    if (result && instr->visit)
+        result = instr->visit(instr, callback, flags, data);
+
+    if (result && (flags & DVF_EXIT))
+        result = callback(instr, DVF_EXIT, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = première instruction à venir ausculter.              *
+*                old   = instruction décompilée à venir remplacer.            *
+*                new   = instruction décompilée à utiliser dorénavant.        *
+*                                                                             *
+*  Description : Remplace une instruction décompilée par une autre.           *
+*                                                                             *
+*  Retour      : true si un remplacement a été effectué, false sinon.         *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_dec_instruction_visit(GDecInstruction *instr, process_decomp_fc process, void *data, bool order)
+bool g_dec_instruction_replace(GDecInstruction *instr, GDecInstruction *old, GDecInstruction *new)
 {
-    if (order)
-        process(instr, data);
+    bool result;                            /* Bilan à retourner           */
 
-    if (instr->visit)
-        instr->visit(instr, process, data, order);
+    if (instr->replace != NULL)
+        result = instr->replace(instr, old, new);
+    else
+        result = false;
 
-    if (!order)
-        process(instr, data);
+    return result;
 
 }
 
diff --git a/src/decomp/instruction.h b/src/decomp/instruction.h
index 810be79..ed8090d 100644
--- a/src/decomp/instruction.h
+++ b/src/decomp/instruction.h
@@ -47,16 +47,26 @@ typedef struct _GDecInstruction GDecInstruction;
 /* Définition d'une instruction décompilée (classe) */
 typedef struct _GDecInstructionClass GDecInstructionClass;
 
+/* Position au cours d'une visite */
+typedef enum _DecInstrVisitFlags
+{
+    DVF_ENTER,                              /* Entrée dans une instruction */
+    DVF_EXIT                                /* Sortie d'une instruction    */
 
-/* Visite un ensemble hiérarchique d'instructions décompilées. */
-typedef void (* process_decomp_fc) (GDecInstruction *, void *);
+} DecInstrVisitFlags;
+
+/* Rappel à chaque instruction décompilée visitée */
+typedef bool (* dec_instr_visitor_cb) (GDecInstruction *, DecInstrVisitFlags, void *);
 
 
 /* Indique le type défini pour une instruction décompilée. */
 GType g_dec_instruction_get_type(void);
 
 /* Visite un ensemble hiérarchique d'instructions décompilées. */
-void g_dec_instruction_visit(GDecInstruction *, process_decomp_fc, void *, bool);
+bool g_dec_instruction_visit(GDecInstruction *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+bool g_dec_instruction_replace(GDecInstruction *, GDecInstruction *, GDecInstruction *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
 GBufferLine *g_dec_instruction_print(const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
-- 
cgit v0.11.2-87-g4458