From f95598b68b98f6eda701f8f02bc09cb13f65fc72 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 28 Nov 2012 09:43:50 +0000
Subject: Followed the excution flow to decompile instructions.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@293 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                          |  61 ++++++
 src/analysis/decomp/Makefile.am    |   4 +-
 src/analysis/decomp/decompiler.c   |  33 +++-
 src/analysis/decomp/il.c           | 382 +++++++++++++++++++++++++++++++++++++
 src/analysis/decomp/il.h           |  38 ++++
 src/analysis/decomp/reduce.c       |  53 +++++
 src/analysis/decomp/reduce.h       |  30 +++
 src/analysis/routine.c             |   2 +-
 src/arch/archbase.c                |  31 +++
 src/arch/archbase.h                |   3 +
 src/arch/dalvik/context.c          |   2 +-
 src/arch/dalvik/decomp/if.c        |  66 +++++++
 src/arch/dalvik/decomp/invoke.c    |  60 ++++++
 src/arch/dalvik/decomp/move.c      |  33 ++++
 src/arch/dalvik/decomp/translate.h |   9 +
 src/arch/dalvik/instruction.c      |  16 +-
 src/decomp/expr/access.c           |  18 +-
 src/decomp/expr/arithm.c           |  17 +-
 src/decomp/expr/array.c            |  20 +-
 src/decomp/expr/assign.c           |  18 +-
 src/decomp/expr/block.c            |  15 +-
 src/decomp/expr/call.c             |  18 +-
 src/decomp/expr/cond.c             |  18 +-
 src/decomp/expr/immediate.c        |   6 +-
 src/decomp/expr/pseudo.c           |   6 +-
 src/decomp/expr/return.c           |  13 +-
 src/decomp/expr/text.c             |   6 +-
 src/decomp/instr/ite.c             |  51 +++--
 src/decomp/instr/ite.h             |   3 +
 src/decomp/instruction-int.h       |   6 +-
 src/decomp/instruction.c           |  36 +++-
 src/decomp/instruction.h           |   9 +-
 src/decomp/lang/java.c             |  84 +++++++-
 src/decomp/output-int.h            |   8 +-
 src/decomp/output.c                |  58 ++++++
 src/decomp/output.h                |   5 +
 36 files changed, 1144 insertions(+), 94 deletions(-)
 create mode 100644 src/analysis/decomp/il.c
 create mode 100644 src/analysis/decomp/il.h
 create mode 100644 src/analysis/decomp/reduce.c
 create mode 100644 src/analysis/decomp/reduce.h

diff --git a/ChangeLog b/ChangeLog
index d9e5efd..9f0f6aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+12-11-28  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/decomp/decompiler.c:
+	Start the decompilation process here.
+
+	* src/analysis/decomp/il.c:
+	* src/analysis/decomp/il.h:
+	New entries: follow the excution flow to decompile instructions.
+
+	* src/analysis/decomp/Makefile.am:
+	Add the il.[ch] and reduce.[ch] files to libanalysisdecomp_la_SOURCES.
+
+	* src/analysis/decomp/reduce.c:
+	* src/analysis/decomp/reduce.h:
+	New entries: to be completed.
+
+	* src/analysis/routine.c:
+	Update code.
+
+	* src/arch/archbase.c:
+	* src/arch/archbase.h:
+	Compare addresses.
+
+	* src/arch/dalvik/context.c:
+	Break the generator of free variables.
+
+	* src/arch/dalvik/decomp/if.c:
+	* src/arch/dalvik/decomp/invoke.c:
+	* src/arch/dalvik/decomp/move.c:
+	* src/arch/dalvik/decomp/translate.h:
+	* src/arch/dalvik/instruction.c:
+	Support more instructions during the decompilation process.
+
+	* 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/immediate.c:
+	* src/decomp/expr/pseudo.c:
+	* src/decomp/expr/return.c:
+	* src/decomp/expr/text.c:
+	Update code.
+
+	* src/decomp/instr/ite.c:
+	* src/decomp/instr/ite.h:
+	Define the two code blocks (then/else) relative to the instruction.
+
+	* src/decomp/instruction.c:
+	* src/decomp/instruction.h:
+	* src/decomp/instruction-int.h:
+	Begin to implement a visitor pattern. Update the code for rendering.
+
+	* src/decomp/lang/java.c:
+	* src/decomp/output.c:
+	* src/decomp/output.h:
+	* src/decomp/output-int.h:
+	Start and finish code block.
+
 12-11-25  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/gui/panels/panel.c:
diff --git a/src/analysis/decomp/Makefile.am b/src/analysis/decomp/Makefile.am
index 7b797bd..27388d6 100755
--- a/src/analysis/decomp/Makefile.am
+++ b/src/analysis/decomp/Makefile.am
@@ -2,7 +2,9 @@
 noinst_LTLIBRARIES = libanalysisdecomp.la
 
 libanalysisdecomp_la_SOURCES =			\
-	decompiler.h decompiler.c
+	decompiler.h decompiler.c			\
+	il.h il.c							\
+	reduce.h reduce.c
 
 libanalysisdecomp_la_LDFLAGS = 
 
diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c
index 8e574c0..91a9163 100644
--- a/src/analysis/decomp/decompiler.c
+++ b/src/analysis/decomp/decompiler.c
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * decompiler.c - encadrement des phases de décompilation
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -32,7 +32,9 @@
 #include <i18n.h>
 
 
+#include "il.h"
 #include "../../decomp/output.h"
+#include "../../decomp/expr/block.h"
 #include "../../decomp/lang/java.h"    /* FIXME : remme ! */
 #include "../../format/format.h"
 
@@ -138,7 +140,11 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c
     size_t i;
 
     GDecContext *context;                   /* Contexte pour la décompil.  */
-    GDecInstruction *instr;
+    GDecInstruction *dinstrs;
+
+    GArchInstruction *instrs;                /* Instructions natives        */
+
+    vmpa_t max;                             /* Première adresse à écarter  */
 
     format = g_loaded_binary_get_format(binary);
     proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
@@ -152,7 +158,28 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c
     {
         context = g_arch_processor_get_decomp_context(proc);
 
-        instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context);
+        g_object_set_data(G_OBJECT(context), "format", format);
+        g_object_set_data(G_OBJECT(context), "routine", routines[i]);
+        g_dec_context_set_max_address(context, max);
+
+        instrs = g_binary_routine_get_instructions(routines[i]);
+
+        max = g_binary_routine_get_address(routines[i])
+            + g_binary_routine_get_size(routines[i]);
+
+        printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i]));
+
+        dinstrs = build_decompiled_block(instrs,
+                                         g_binary_routine_get_address(routines[i]),
+                                         max, VMPA_MAX, context);
+
+        //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context);
+
+
+
+        g_binary_routine_set_decomp_instructions(routines[i], dinstrs);
+
+
 
         if (context != NULL)
             g_object_unref(context);
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
new file mode 100644
index 0000000..d9b9588
--- /dev/null
+++ b/src/analysis/decomp/il.c
@@ -0,0 +1,382 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * il.h - mise en place d'un langage intermédiaire
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA 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.
+ *
+ *  OpenIDA 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 "il.h"
+
+
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "../../decomp/expr/block.h"
+#include "../../decomp/instr/ite.h"
+
+
+
+/* Indications sur une branche */
+typedef struct _branch_info
+{
+    vmpa_t *jumps;                          /* Jalons de la branche        */
+    size_t count;                           /* Quantité de ces jalons      */
+
+} branch_info;
+
+
+/* Indique si une adresse est retenue comme point de passage. */
+static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool);
+
+/* Identifie les différents points de passage d'une branche. */
+static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *);
+
+/* Retrouve le point de ralliement entre deux branches. */
+static vmpa_t compute_first_common_addr(branch_info *, branch_info *);
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info = informations à consulter.                             *
+*                addr = adresse à rechercher.                                 *
+*                fast = autorise une recherche rapide.                        *
+*                                                                             *
+*  Description : Indique si une adresse est retenue comme point de passage.   *
+*                                                                             *
+*  Retour      : true si le jalon est déjà dans la liste, false sinon.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    void *ptr;                              /* Résultat des recherches     */
+
+    result = false;
+
+    if (!fast)
+        for (i = 0; i < info->count && !result; i++)
+            result = (info->jumps[i] == *addr);
+
+    else
+    {
+        ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+        result = (ptr != NULL);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instrs = ensemble des instructions d'assemblage.             *
+*                start  = adresse de début du bloc.                           *
+*                end    = adresse de fin du bloc (exclusive).                 *
+*                count  = nombre de sauts détectés. [OUT]                     *
+*                                                                             *
+*  Description : Identifie les différents points de passage d'une branche.    *
+*                                                                             *
+*  Retour      : Jalons dans le flot d'exécution.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info)
+{
+    GArchInstruction *iter;                 /* Boucle de parcours #1       */
+    GArchInstruction **dests;               /* Instr. visée par une autre  */
+    InstructionLinkType *types;             /* Type de lien entre lignes   */
+    size_t dcount;                          /* Nombre de liens de dest.    */
+    size_t i;                               /* Boucle de parcours #2       */
+    vmpa_t addr;                            /* Adresse de la destination   */
+
+    /* On évite de boucler... */
+    if (is_addr_in_branch(info, &start, false))
+        return;
+
+    info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
+    info->jumps[info->count - 1] = start;
+
+    /* On suit le flot jusqu'à la prochaine bifurcation */
+    for (iter = g_arch_instruction_find_by_address(instrs, start, true);
+         iter != NULL;
+         iter = g_arch_instruction_get_next_iter(instrs, iter, end))
+    {
+        if (!g_arch_instruction_has_destinations(iter))
+            continue;
+
+        dcount = g_arch_instruction_get_destinations(iter, &dests, &types);
+
+        for (i = 0; i < dcount; i++)
+            switch (types[i])
+            {
+                case ILT_EXEC_FLOW:
+                case ILT_JUMP:
+                case ILT_JUMP_IF_TRUE:
+                case ILT_JUMP_IF_FALSE:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    find_next_jumps(instrs, addr, end, info);
+                    break;
+
+                default:
+                    break;
+
+            }
+
+        break;
+
+    }
+
+    /* Si on termine... */
+    if (iter != NULL && !is_addr_in_branch(info, &end, false))
+    {
+        info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
+        info->jumps[info->count - 1] = end;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier ensemble de jalons à parcourir.                  *
+*                b = second ensemble de jalons à parcourir.                   *
+*                                                                             *
+*  Description : Retrouve le point de ralliement entre deux branches.         *
+*                                                                             *
+*  Retour      : Adresse commune à deux branches.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b)
+{
+    vmpa_t result;                          /* Adresse trouvée à retourner */
+    size_t i;                               /* Boucle de parcours          */
+
+    /* Valeur conceptuellement impossible à renvoyer */
+    result = VMPA_MAX;
+
+    //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+    //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+
+    for (i = 0; i < a->count && result == VMPA_MAX; i++)
+        if (is_addr_in_branch(b, &a->jumps[i], false))
+            result = a->jumps[i];
+
+    return result;
+
+}
+
+
+
+#include "../../arch/processor.h"
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instrs = ensemble des instructions d'assemblage.             *
+*                start  = adresse de début du bloc.                           *
+*                end    = adresse de fin du bloc (exclusive).                 *
+*                stop   = adresse d'arrêt en cas de saut ou VMPA_MAX.         *
+*                ctx    = contexte de soutien à associer à l'opération.       *
+*                                                                             *
+*  Description : Procède à la décompilation basique d'un bloc déterminé.      *
+*                                                                             *
+*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop, GDecContext *ctx)
+{
+    GDecInstruction *result;                /* Instructions décompilées    */
+    GArchInstruction *iter;                 /* Boucle de parcours          */
+
+    GDecInstruction *pite;                  /* IfThenElse potientiel...    */
+
+    GArchInstruction **dests;               /* Instr. visée par une autre  */
+    InstructionLinkType *types;             /* Type de lien entre lignes   */
+    size_t dcount;                          /* Nombre de liens de dest.    */
+
+    size_t i;                               /* Boucle de parcours          */
+    vmpa_t addr;                            /* Adresse de la destination   */
+
+    branch_info true_branch;                /* Branche 'condition vraie'   */
+    branch_info false_branch;               /* Branche 'condition fausse'  */
+    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */
+    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */
+
+    vmpa_t next_addr;                       /* Prochaine instruction visée */
+
+    GDecInstruction *first;                 /* Première décompilation      */
+    GDecInstruction *dinstr;                /* Nouvelle décompilation      */
+
+
+    GExeFormat *format;                     /* Format du binaire fourni    */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    GDecContext *context;                   /* Contexte pour la décompil.  */
+
+
+    result = NULL;
+
+    printf("[+] processing 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop);
+
+    for (iter = g_arch_instruction_find_by_address(instrs, start, true);
+         iter != NULL;
+         )
+    {
+        /* On s'arrêter si l'instruction est déjà décompilée */
+        if (g_object_get_data(G_OBJECT(iter), "decomp_done") != NULL) break;
+        g_object_set_data(G_OBJECT(iter), "decomp_done", iter);
+
+        pite = g_arch_instruction_decompile(iter, ctx);
+
+        g_arch_instruction_get_location(iter, NULL, NULL, &addr);
+        printf(" --- decomp %p @ 0x%08llx\n", pite, addr);
+
+        /* On n'approfondit que les chemins qui se séparent */
+        if (!g_arch_instruction_has_destinations(iter))
+        {
+            iter = g_arch_instruction_get_next_iter(instrs, iter, end);
+            continue;
+        }
+
+        /* Adaptations en fonction du type de bifurcation */
+
+        dcount = g_arch_instruction_get_destinations(iter, &dests, &types);
+
+        next_addr = 0;
+        memset(&true_branch, 0, sizeof(branch_info));
+        memset(&false_branch, 0, sizeof(branch_info));
+
+        for (i = 0; i < dcount; i++)
+            switch (types[i])
+            {
+                case ILT_EXEC_FLOW:
+                case ILT_JUMP:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr);
+                    break;
+
+                case ILT_JUMP_IF_TRUE:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    find_next_jumps(instrs, addr, end, &true_branch);
+                    break;
+
+                case ILT_JUMP_IF_FALSE:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    find_next_jumps(instrs, addr, end, &false_branch);
+                    break;
+
+                default:
+                    next_addr = VMPA_MAX;
+                    break;
+
+            }
+
+        if (next_addr == VMPA_MAX)
+        {
+            iter = g_arch_instruction_get_next_iter(instrs, iter, end);
+            continue;
+        }
+
+        else if (true_branch.count > 0 || false_branch.count > 0)
+        {
+            next_addr = compute_first_common_addr(&true_branch, &false_branch);
+            next_addr = MIN(next_addr, end);
+
+            format = g_object_get_data(G_OBJECT(ctx), "format");
+            proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
+
+            context = g_arch_processor_get_decomp_context(proc);
+
+            g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format"));
+            g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine"));
+            g_dec_context_set_max_address(context, next_addr);
+
+            true_dinstr = build_decompiled_block(instrs, true_branch.jumps[0],
+                                                 end, next_addr, context);
+
+
+            context = g_arch_processor_get_decomp_context(proc);
+
+            g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format"));
+            g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine"));
+            g_dec_context_set_max_address(context, next_addr);
+
+            false_dinstr = build_decompiled_block(instrs, false_branch.jumps[0],
+                                                  end, next_addr, context);
+
+
+            printf("{branch : %p (0x%08llx) | %p (0x%08llx)\n",
+                   true_dinstr, true_branch.jumps[0],
+                   false_dinstr, false_branch.jumps[0]);
+
+            g_ite_instruction_set_branches(G_ITE_INSTRUCTION(pite), true_dinstr, false_dinstr);
+
+            if (next_addr == end) break;
+
+        }
+
+        /* Détermination du prochain point de chute */
+
+        if (next_addr == stop) break;
+
+        iter = g_arch_instruction_find_by_address(instrs, next_addr, true);
+
+    }
+
+
+
+
+    first = g_dec_context_get_decomp_instrs(ctx);
+
+    printf(" ... context instr : %p\n", first);
+
+    for (dinstr = first;
+         dinstr != NULL;
+         dinstr = g_dec_instruction_get_next_iter(first, dinstr))
+    {
+        if (result == NULL) result = g_expr_block_new(dinstr);
+        else g_expr_block_add_item(G_EXPR_BLOCK(result), dinstr);
+
+    }
+
+    printf(" ... return %p\n", result);
+
+    return result;
+
+}
diff --git a/src/analysis/decomp/il.h b/src/analysis/decomp/il.h
new file mode 100644
index 0000000..4f38b4f
--- /dev/null
+++ b/src/analysis/decomp/il.h
@@ -0,0 +1,38 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * il.h - prototypes pour la mise en place d'un langage intermédiaire
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA 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.
+ *
+ *  OpenIDA 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_DECOMP_IL_H
+#define _ANALYSIS_DECOMP_IL_H
+
+
+#include "../../arch/instruction.h"
+#include "../../decomp/instruction.h"
+
+
+
+/* Procède à la décompilation basique d'un bloc déterminé. */
+GDecInstruction *build_decompiled_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t, GDecContext *);
+
+
+
+#endif  /* _ANALYSIS_DECOMP_IL_H */
diff --git a/src/analysis/decomp/reduce.c b/src/analysis/decomp/reduce.c
new file mode 100644
index 0000000..926650d
--- /dev/null
+++ b/src/analysis/decomp/reduce.c
@@ -0,0 +1,53 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * reduce.c - réduction de l'usage des [pseudo]-registres
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA 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.
+ *
+ *  OpenIDA 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 "reduce.h"
+
+
+#if 0
+
+
+
+/* Mémorisation de l'usage de chaque variable */
+typedef struct _var_usage
+{
+    GDecInstruction *var;                   /* Variable manipulée          */
+
+    size_t ref_counter;                     /* Décompte des utilisations   */
+    GDecInstruction *creation;              /* Emplacement de la création  */
+    GDecInstruction *usage;                 /* Lieu de dernère utilisation */
+
+} var_usage;
+
+/* Réduction des usages */
+typedef struct _usage_reduc
+{
+
+
+
+} usage_reduc;
+
+
+#endif
+
+
diff --git a/src/analysis/decomp/reduce.h b/src/analysis/decomp/reduce.h
new file mode 100644
index 0000000..aa13d7f
--- /dev/null
+++ b/src/analysis/decomp/reduce.h
@@ -0,0 +1,30 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * reduce.h - prototypes pour la réduction de l'usage des [pseudo]-registres
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA 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.
+ *
+ *  OpenIDA 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_DECOMP_REDUCE_H
+#define _ANALYSIS_DECOMP_REDUCE_H
+
+
+
+
+#endif  /* _ANALYSIS_DECOMP_REDUCE_H */
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index a21b6e7..7a191c9 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -998,7 +998,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang,
         g_lang_output_start_routine_body(lang, buffer, line);
 
         if (routine->dinstr != NULL)
-            g_dec_instruction_print(routine->dinstr, buffer, NULL, lang);
+            g_dec_instruction_print(routine->dinstr, buffer, line, lang);
 
         g_lang_output_end_routine_body(lang, buffer);
 
diff --git a/src/arch/archbase.c b/src/arch/archbase.c
index 6241164..e422971 100644
--- a/src/arch/archbase.c
+++ b/src/arch/archbase.c
@@ -31,6 +31,37 @@
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : a = première adresse à comparer.                             *
+*                b = seconde adresse à comparer.                              *
+*                                                                             *
+*  Description : Etablit la comparaison entre deux adresses.                  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int compare_vmpa(const vmpa_t *a, const vmpa_t *b)
+{
+    int result;                             /* Bilan à retourner           */
+
+    if (*a < *b)
+        result = -1;
+
+    else if (*a == *b)
+        result = 0;
+
+    else
+        result = 1;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
 *                msize  = taille de cette adresse.                            *
 *                buffer = chaîne de caractères à constituer. [OUT]            *
diff --git a/src/arch/archbase.h b/src/arch/archbase.h
index 0886e26..b21d52c 100644
--- a/src/arch/archbase.h
+++ b/src/arch/archbase.h
@@ -80,6 +80,9 @@ typedef enum _AsmSyntax
 
 
 
+/* Etablit la comparaison entre deux adresses. */
+int compare_vmpa(const vmpa_t *, const vmpa_t *);
+
 /* Transforme une adresse en chaîne de caractères. */
 size_t vmpa_to_string(vmpa_t, MemoryDataSize, char [VMPA_MAX_SIZE]);
 
diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c
index c7b5ee6..e5041cb 100644
--- a/src/arch/dalvik/context.c
+++ b/src/arch/dalvik/context.c
@@ -430,7 +430,7 @@ static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx,
     {
         found = g_hash_table_lookup(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info)));
 
-        if (!assign && found != NULL)
+        if (/*!assign && */found != NULL)
         {
             g_object_ref(G_OBJECT(found));
             result = G_DEC_INSTRUCTION(found);
diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c
index 43406c7..b274ead 100644
--- a/src/arch/dalvik/decomp/if.c
+++ b/src/arch/dalvik/decomp/if.c
@@ -93,3 +93,69 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte
     return result;
 
 }
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction d'origine à convertir.                   *
+*                ctx   = contexte de la phase de décompilation.               *
+*                                                                             *
+*  Description : Décompile une instruction de comparaison d'opérandes.        *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDecContext *ctx)
+{
+    GDecInstruction *result;                /* Instruction à retourner     */
+    CompSignType sign;                      /* Type d'opération menée      */
+    GArchOperand *operand;                  /* Opérande de l'instruction   */
+    GDecInstruction *op1;                   /* Premier opérande utilisé    */
+    GDecInstruction *op2;                   /* Second opérande utilisé     */
+    vmpa_t jmp;                             /* Adresse de saut             */
+    GDecInstruction *cond;                  /* Comparaison à restituer     */
+
+    switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr)))
+    {
+        case DOP_IF_EQ:
+            sign = CST_EQ;
+            break;
+        case DOP_IF_NE:
+            sign = CST_NE;
+            break;
+        case DOP_IF_LT:
+            sign = CST_LT;
+            break;
+        case DOP_IF_GE:
+            sign = CST_GE;
+            break;
+        case DOP_IF_GT:
+            sign = CST_GT;
+            break;
+        case DOP_IF_LE:
+            sign = CST_LE;
+            break;
+        default:
+            sign = CST_COUNT;
+            break;
+    }
+
+    operand = g_arch_instruction_get_operand(instr, 0);
+    op1 = g_dec_context_convert_register(ctx, operand, false);
+
+    operand = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, (unsigned int)0);
+    op2 = g_imm_expression_new(operand);
+
+    operand = g_arch_instruction_get_operand(instr, 2);
+    jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand);*/
+
+    cond = g_cond_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2));
+    result = g_ite_instruction_new(G_DEC_EXPRESSION(cond), jmp, jmp);
+
+    return result;
+
+}
diff --git a/src/arch/dalvik/decomp/invoke.c b/src/arch/dalvik/decomp/invoke.c
index c3650b4..6f863be 100644
--- a/src/arch/dalvik/decomp/invoke.c
+++ b/src/arch/dalvik/decomp/invoke.c
@@ -144,6 +144,66 @@ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr
 *  Paramètres  : instr = instruction d'origine à convertir.                   *
 *                ctx   = contexte de la phase de décompilation.               *
 *                                                                             *
+*  Description : Décompile une instruction de type 'invoke-static'.           *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *instr, GDecContext *ctx)
+{
+    GDecInstruction *result;                /* Instruction à retourner     */
+    size_t count;                           /* Quantité d'opérandes        */
+    GArchOperand *operand;                  /* Opérande de l'instruction   */
+    uint32_t index;                         /* Indice de l'élément visé    */
+    GDexFormat *format;                     /* Accès aux constantes        */
+    GBinRoutine *routine;                   /* Routine visée par l'appel   */
+    GDecInstruction *call;                  /* Représentation de l'appel   */
+    size_t i;                               /* Boucle de parcours #2       */
+    GArchOperand *arg;                      /* Argument brut de l'appel    */
+    GDecInstruction *reg;                   /* Argument converti           */
+
+    result = NULL;
+
+    /* Récupération de la méthode */
+
+    count = g_arch_instruction_count_operands(instr);
+    operand = g_arch_instruction_get_operand(instr, count - 1);
+
+    index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand));
+
+    format = G_DEX_FORMAT(g_object_get_data(G_OBJECT(ctx), "format"));
+    routine = get_routine_from_dex_pool(format, index);
+    if (routine == NULL) return NULL;
+
+    call = g_routine_call_new(routine);
+
+    /* Ajout des arguments */
+
+    operand = g_arch_instruction_get_operand(instr, 0);
+    count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand));
+
+    for (i = 0; i < count; i++)
+    {
+        arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i);
+        reg = g_dec_context_convert_register(ctx, arg, false);
+
+        g_routine_call_add_arg(G_ROUTINE_CALL(call), reg);
+
+    }
+
+    return call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction d'origine à convertir.                   *
+*                ctx   = contexte de la phase de décompilation.               *
+*                                                                             *
 *  Description : Décompile une instruction de type 'invoke-virtual'.          *
 *                                                                             *
 *  Retour      : Instruction mise en place ou NULL.                           *
diff --git a/src/arch/dalvik/decomp/move.c b/src/arch/dalvik/decomp/move.c
index f700737..9165447 100644
--- a/src/arch/dalvik/decomp/move.c
+++ b/src/arch/dalvik/decomp/move.c
@@ -33,6 +33,39 @@
 *  Paramètres  : instr = instruction d'origine à convertir.                   *
 *                ctx   = contexte de la phase de décompilation.               *
 *                                                                             *
+*  Description : Décompile une instruction de type 'move'.                    *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *instr, GDecContext *ctx)
+{
+    GDecInstruction *result;                /* Instruction à retourner     */
+    GArchOperand *operand;                  /* Opérande de l'instruction   */
+    GDecInstruction *src;                   /* Registre de l'object        */
+    GDecInstruction *dest;                  /* Registre de destination     */
+
+    operand = g_arch_instruction_get_operand(instr, 1);
+    src = g_dec_context_convert_register(ctx, operand, false);
+
+    operand = g_arch_instruction_get_operand(instr, 0);
+    dest = g_dec_context_convert_register(ctx, operand, true);
+
+    result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(src));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction d'origine à convertir.                   *
+*                ctx   = contexte de la phase de décompilation.               *
+*                                                                             *
 *  Description : Décompile une instruction de type 'move-object'.             *
 *                                                                             *
 *  Retour      : Instruction mise en place ou NULL.                           *
diff --git a/src/arch/dalvik/decomp/translate.h b/src/arch/dalvik/decomp/translate.h
index 7779ab7..b8753db 100644
--- a/src/arch/dalvik/decomp/translate.h
+++ b/src/arch/dalvik/decomp/translate.h
@@ -50,12 +50,18 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *, GDecContext
 /* Décompile une instruction de type 'invoke-direct'. */
 GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *, GDecContext *);
 
+/* Décompile une instruction de type 'invoke-static'. */
+GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *, GDecContext *);
+
 /* Décompile une instruction de type 'invoke-virtual'. */
 GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *, GDecContext *);
 
 /* Décompile une instruction de type 'iput'. */
 GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *, GDecContext *);
 
+/* Décompile une instruction de type 'move'. */
+GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *, GDecContext *);
+
 /* Décompile une instruction de type 'move-object'. */
 GDecInstruction *dalvik_decomp_instr_move_object(const GArchInstruction *, GDecContext *);
 
@@ -84,6 +90,9 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *, GDecCo
 /* Décompile une instruction de comparaison d'opérandes. */
 GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *, GDecContext *);
 
+/* Décompile une instruction de comparaison d'opérandes. */
+GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *, GDecContext *);
+
 
 
 #endif  /* _ANALYSIS_DECOMP_RTL_DALVIK_TRANSLATE_H */
diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c
index f0e679f..5f3a1f4 100644
--- a/src/arch/dalvik/instruction.c
+++ b/src/arch/dalvik/instruction.c
@@ -57,7 +57,7 @@ typedef struct _dalvik_instruction
 static dalvik_instruction _instructions[DOP_COUNT] = {
 
     [DOP_NOP]                   = { 0x00, "nop",                NULL },
-    [DOP_MOVE]                  = { 0x01, "move" },
+    [DOP_MOVE]                  = { 0x01, "move",               dalvik_decomp_instr_move },
     [DOP_MOVE_FROM_16]          = { 0x02, "move/from16" },
     [DOP_MOVE_16]               = { 0x03, "move/16" },
     [DOP_MOVE_WIDE]             = { 0x04, "move-wide" },
@@ -112,12 +112,12 @@ static dalvik_instruction _instructions[DOP_COUNT] = {
     [DOP_IF_GE]                 = { 0x35, "if-ge",              dalvik_decomp_instr_if },
     [DOP_IF_GT]                 = { 0x36, "if-gt",              dalvik_decomp_instr_if },
     [DOP_IF_LE]                 = { 0x37, "if-le",              dalvik_decomp_instr_if },
-    [DOP_IF_EQZ]                = { 0x38, "if-eqz" },
-    [DOP_IF_NEZ]                = { 0x39, "if-nez" },
-    [DOP_IF_LTZ]                = { 0x3a, "if-ltz" },
-    [DOP_IF_GEZ]                = { 0x3b, "if-gez" },
-    [DOP_IF_GTZ]                = { 0x3c, "if-gtz" },
-    [DOP_IF_LEZ]                = { 0x3d, "if-lez" },
+    [DOP_IF_EQZ]                = { 0x38, "if-eqz",             dalvik_decomp_instr_if_zero },
+    [DOP_IF_NEZ]                = { 0x39, "if-nez",             dalvik_decomp_instr_if_zero },
+    [DOP_IF_LTZ]                = { 0x3a, "if-ltz",             dalvik_decomp_instr_if_zero },
+    [DOP_IF_GEZ]                = { 0x3b, "if-gez",             dalvik_decomp_instr_if_zero },
+    [DOP_IF_GTZ]                = { 0x3c, "if-gtz",             dalvik_decomp_instr_if_zero },
+    [DOP_IF_LEZ]                = { 0x3d, "if-lez",             dalvik_decomp_instr_if_zero },
     [DOP_UNUSED_3E]             = { 0x3e, NULL /* unused */ },
     [DOP_UNUSED_3F]             = { 0x3f, NULL /* unused */ },
     [DOP_UNUSED_40]             = { 0x40, NULL /* unused */ },
@@ -169,7 +169,7 @@ static dalvik_instruction _instructions[DOP_COUNT] = {
     [DOP_INVOKE_VIRTUAL]        = { 0x6e, "invoke-virtual",     dalvik_decomp_instr_invoke_virtual },
     [DOP_INVOKE_SUPER]          = { 0x6f, "invoke-static" },
     [DOP_INVOKE_DIRECT]         = { 0x70, "invoke-direct",      dalvik_decomp_instr_invoke_direct },
-    [DOP_INVOKE_STATIC]         = { 0x71, "invoke-static" },
+    [DOP_INVOKE_STATIC]         = { 0x71, "invoke-static",      dalvik_decomp_instr_invoke_static },
     [DOP_INVOKE_INTERFACE]      = { 0x72, "invoke-interface" },
     [DOP_UNUSED_73]             = { 0x73, NULL /* unused */ },
     [DOP_INVOKE_VIRTUAL_RANGE]  = { 0x74, "invoke-virtual/range" },
diff --git a/src/decomp/expr/access.c b/src/decomp/expr/access.c
index e2cbf19..277209a 100644
--- a/src/decomp/expr/access.c
+++ b/src/decomp/expr/access.c
@@ -55,7 +55,7 @@ static void g_access_expression_class_init(GAccessExpressionClass *);
 static void g_access_expression_init(GAccessExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_access_expression_print(const GAccessExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_access_expression_print(const GAccessExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -146,14 +146,18 @@ GDecInstruction *g_access_expression_new(GDecExpression *owner, GDecExpression *
 *                                                                             *
 ******************************************************************************/
 
-static void g_access_expression_print(const GAccessExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_access_expression_print(const GAccessExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->owner),
-                            buffer, line, output);
+    GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->owner),
+                                     buffer, line, output);
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->target),
-                            buffer, line, output);
+    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ".", 3, RTT_PUNCT);
+
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->target),
+                                     buffer, result, output);
+
+    return result;
 
 }
diff --git a/src/decomp/expr/arithm.c b/src/decomp/expr/arithm.c
index 0ca73ac..d91e080 100644
--- a/src/decomp/expr/arithm.c
+++ b/src/decomp/expr/arithm.c
@@ -57,7 +57,7 @@ static void g_arithm_expression_class_init(GArithmExpressionClass *);
 static void g_arithm_expression_init(GArithmExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_arithm_expression_print(const GArithmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_arithm_expression_print(const GArithmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -151,12 +151,13 @@ GDecInstruction *g_arithm_expression_new(GDecExpression *op1, ArithmOperationTyp
 *                                                                             *
 ******************************************************************************/
 
-static void g_arithm_expression_print(const GArithmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_arithm_expression_print(const GArithmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
+    GBufferLine *result;                    /* Ligne à retourner           */
     const char *sign;                       /* Symbole de l'opération      */
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op1),
-                            buffer, line, output);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op1),
+                                     buffer, line, output);
 
     switch (expr->type)
     {
@@ -189,9 +190,11 @@ static void g_arithm_expression_print(const GArithmExpression *expr, GCodeBuffer
             break;
     }
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, sign, 3, RTT_SIGNS);
+    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, sign, 3, RTT_SIGNS);
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op2),
-                            buffer, line, output);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->op2),
+                                     buffer, result, output);
+
+    return result;
 
 }
diff --git a/src/decomp/expr/array.c b/src/decomp/expr/array.c
index c14374b..dc487ee 100644
--- a/src/decomp/expr/array.c
+++ b/src/decomp/expr/array.c
@@ -55,7 +55,7 @@ static void g_array_access_class_init(GArrayAccessClass *);
 static void g_array_access_init(GArrayAccess *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_array_access_print(const GArrayAccess *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_array_access_print(const GArrayAccess *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -146,16 +146,20 @@ GDecInstruction *g_array_access_new(GDecExpression *array, GDecExpression *index
 *                                                                             *
 ******************************************************************************/
 
-static void g_array_access_print(const GArrayAccess *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_array_access_print(const GArrayAccess *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->array),
-                            buffer, line, output);
+    GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "[", 1, RTT_RAW);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->array),
+                                     buffer, line, output);
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->index),
-                            buffer, line, output);
+    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "[", 1, RTT_RAW);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "]", 1, RTT_RAW);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->index),
+                                     buffer, result, output);
+
+    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "]", 1, RTT_RAW);
+
+    return result;
 
 }
diff --git a/src/decomp/expr/assign.c b/src/decomp/expr/assign.c
index 0843776..fd86021 100644
--- a/src/decomp/expr/assign.c
+++ b/src/decomp/expr/assign.c
@@ -55,7 +55,7 @@ static void g_assign_expression_class_init(GAssignExpressionClass *);
 static void g_assign_expression_init(GAssignExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_assign_expression_print(const GAssignExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_assign_expression_print(const GAssignExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -146,15 +146,19 @@ GDecInstruction *g_assign_expression_new(GDecExpression *dest, GDecExpression *s
 *                                                                             *
 ******************************************************************************/
 
-static void g_assign_expression_print(const GAssignExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_assign_expression_print(const GAssignExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest),
-                            buffer, line, output);
+    GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest),
+                                     buffer, line, output);
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src),
-                            buffer, line, output);
+    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS);
+
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src),
+                                     buffer, result, output);
+
+    return result;
 
 }
 
diff --git a/src/decomp/expr/block.c b/src/decomp/expr/block.c
index 1ec15a7..5124204 100644
--- a/src/decomp/expr/block.c
+++ b/src/decomp/expr/block.c
@@ -58,7 +58,7 @@ static void g_expr_block_class_init(GExprBlockClass *);
 static void g_expr_block_init(GExprBlock *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_expr_block_print(const GExprBlock *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_expr_block_print(const GExprBlock *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -147,19 +147,26 @@ GDecInstruction *g_expr_block_new(GDecInstruction *item)
 *                                                                             *
 ******************************************************************************/
 
-static void g_expr_block_print(const GExprBlock *block, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_expr_block_print(const GExprBlock *block, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
+    GBufferLine *result;                    /* Ligne à retourner           */
     size_t i;                               /* Boucle de parcours          */
 
+    result = g_lang_output_start_code_block(output, buffer, line, block->count);
+
     for (i = 0; i < block->count; i++)
     {
         if (i > 0)
-            line = g_code_buffer_append_new_line_fixme(buffer);   /* FIXME : n° de ligne */
+            result = g_code_buffer_append_new_line_fixme(buffer);   /* FIXME : n° de ligne */
 
-        g_dec_instruction_print(block->list[i], buffer, line, output);
+        result = g_dec_instruction_print(block->list[i], buffer, result, output);
 
     }
 
+    result = g_lang_output_end_code_block(output, buffer, result, block->count);
+
+    return result;
+
 }
 
 
diff --git a/src/decomp/expr/call.c b/src/decomp/expr/call.c
index aaf9883..e518c6f 100644
--- a/src/decomp/expr/call.c
+++ b/src/decomp/expr/call.c
@@ -61,7 +61,7 @@ static void g_routine_call_class_init(GRoutineCallClass *);
 static void g_routine_call_init(GRoutineCall *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_routine_call_print(const GRoutineCall *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_routine_call_print(const GRoutineCall *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -150,8 +150,9 @@ GDecInstruction *g_routine_call_new(GBinRoutine *routine)
 *                                                                             *
 ******************************************************************************/
 
-static void g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
+    GBufferLine *result;                    /* Ligne à retourner           */
     const char *name;                       /* Désignation de la routine   */
     size_t i;                               /* Boucle de parcours          */
 
@@ -162,20 +163,23 @@ static void g_routine_call_print(const GRoutineCall *call, GCodeBuffer *buffer,
 
     if (call->count > 0)
     {
-        g_dec_instruction_print(call->args[0], buffer, line, output);
+        result = g_dec_instruction_print(call->args[0], buffer, line, output);
 
         for (i = 1; i < call->count; i++)
         {
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ",", 1, RTT_PUNCT);
-            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ",", 1, RTT_PUNCT);
+            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
 
-            g_dec_instruction_print(call->args[i], buffer, line, output);
+            g_dec_instruction_print(call->args[i], buffer, result, output);
 
         }
 
     }
+    else result = line;
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT);
+    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT);
+
+    return result;
 
 }
 
diff --git a/src/decomp/expr/cond.c b/src/decomp/expr/cond.c
index 51309ca..4a9b63b 100644
--- a/src/decomp/expr/cond.c
+++ b/src/decomp/expr/cond.c
@@ -56,7 +56,7 @@ static void g_cond_expression_class_init(GCondExpressionClass *);
 static void g_cond_expression_init(GCondExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -149,14 +149,18 @@ GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDe
 *                                                                             *
 ******************************************************************************/
 
-static void g_cond_expression_print(const GCondExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_cond_expression_print(const GCondExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a),
-                            buffer, line, output);
+    GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_lang_output_write_comp_sign(output, line, expr->sign);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a),
+                                     buffer, line, output);
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b),
-                            buffer, line, output);
+    g_lang_output_write_comp_sign(output, result, expr->sign);
+
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b),
+                                     buffer, result, output);
+
+    return result;
 
 }
diff --git a/src/decomp/expr/immediate.c b/src/decomp/expr/immediate.c
index a97c8bd..a17b2a1 100644
--- a/src/decomp/expr/immediate.c
+++ b/src/decomp/expr/immediate.c
@@ -54,7 +54,7 @@ static void g_imm_expression_class_init(GImmExpressionClass *);
 static void g_imm_expression_init(GImmExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_imm_expression_print(const GImmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_imm_expression_print(const GImmExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -143,8 +143,10 @@ GDecInstruction *g_imm_expression_new(GImmOperand *operand)
 *                                                                             *
 ******************************************************************************/
 
-static void g_imm_expression_print(const GImmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_imm_expression_print(const GImmExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
     g_arch_operand_print(G_ARCH_OPERAND(expr->operand), line, ASX_COUNT);
 
+    return line;
+
 }
diff --git a/src/decomp/expr/pseudo.c b/src/decomp/expr/pseudo.c
index e73cb3d..9da76e7 100644
--- a/src/decomp/expr/pseudo.c
+++ b/src/decomp/expr/pseudo.c
@@ -61,7 +61,7 @@ static void g_pseudo_register_class_init(GPseudoRegisterClass *);
 static void g_pseudo_register_init(GPseudoRegister *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_pseudo_register_print(const GPseudoRegister *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_pseudo_register_print(const GPseudoRegister *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -148,7 +148,7 @@ GDecInstruction *g_pseudo_register_new(void)
 *                                                                             *
 ******************************************************************************/
 
-static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
     char label[32];
     char *name;
@@ -165,6 +165,8 @@ static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buf
         g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_RAW);
     }
 
+    return line;
+
 }
 
 
diff --git a/src/decomp/expr/return.c b/src/decomp/expr/return.c
index e29f022..a9c10d9 100644
--- a/src/decomp/expr/return.c
+++ b/src/decomp/expr/return.c
@@ -54,7 +54,7 @@ static void g_return_expression_class_init(GReturnExpressionClass *);
 static void g_return_expression_init(GReturnExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_return_expression_print(const GReturnExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_return_expression_print(const GReturnExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -143,17 +143,22 @@ GDecInstruction *g_return_expression_new(GDecExpression *payload)
 *                                                                             *
 ******************************************************************************/
 
-static void g_return_expression_print(const GReturnExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_return_expression_print(const GReturnExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
+    GBufferLine *result;                    /* Ligne à retourner           */
+
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "return", 6, RTT_KEY_WORD);
 
     if (expr->payload != NULL)
     {
         g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
 
-        g_dec_instruction_print(G_DEC_INSTRUCTION(expr->payload),
-                                buffer, line, output);
+        result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->payload),
+                                         buffer, line, output);
 
     }
+    else result = line;
+
+    return result;
 
 }
diff --git a/src/decomp/expr/text.c b/src/decomp/expr/text.c
index d62e689..8fa7e34 100644
--- a/src/decomp/expr/text.c
+++ b/src/decomp/expr/text.c
@@ -58,7 +58,7 @@ static void g_str_expression_class_init(GStrExpressionClass *);
 static void g_str_expression_init(GStrExpression *);
 
 /* Imprime pour l'écran un version humaine d'une expression. */
-static void g_str_expression_print(const GStrExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_str_expression_print(const GStrExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -148,10 +148,12 @@ GDecInstruction *g_str_expression_new(const char *value)
 *                                                                             *
 ******************************************************************************/
 
-static void g_str_expression_print(const GStrExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_str_expression_print(const GStrExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING);
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, expr->value, expr->len, RTT_STRING);
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "\"", 1, RTT_STRING);
 
+    return line;
+
 }
diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c
index f08df1e..7c68031 100644
--- a/src/decomp/instr/ite.c
+++ b/src/decomp/instr/ite.c
@@ -35,6 +35,9 @@ struct _GITEInstruction
 
     GDecExpression *cond;                   /* Condition prise en compte   */
 
+    GDecInstruction *true_branch;           /* Condition vérifiée          */
+    GDecInstruction *false_branch;          /* Condition non vérifiée      */
+
     union
     {
         vmpa_t addr;                        /* Adresse de saut             */
@@ -68,7 +71,7 @@ static void g_ite_instruction_class_init(GITEInstructionClass *);
 static void g_ite_instruction_init(GITEInstruction *);
 
 /* Imprime pour l'écran un version humaine d'une instruction. */
-static void g_ite_instruction_print(const GITEInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+static GBufferLine *g_ite_instruction_print(const GITEInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
@@ -148,6 +151,28 @@ 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.  *
+*                                                                             *
+*  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)
+{
+    expr->true_branch = true_branch;
+    expr->false_branch = false_branch;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : expr   = instruction à transcrire en version humaine.        *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
@@ -161,22 +186,24 @@ GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmp
 *                                                                             *
 ******************************************************************************/
 
-static void g_ite_instruction_print(const GITEInstruction *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD);
+    GBufferLine *result;                    /* Ligne à retourner           */
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond),
-                            buffer, line, output);
+    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD);
 
-    /*
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->dest),
-                            buffer, line, output);
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond),
+                                     buffer, line, output);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " = ", 3, RTT_SIGNS);
+    if (expr->true_branch != NULL)
+        result = g_dec_instruction_print(expr->true_branch, buffer, result, output);
 
-    g_dec_instruction_print(G_DEC_INSTRUCTION(expr->src),
-                            buffer, line, output);
-    */
+    if (expr->false_branch != NULL)
+    {
+        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "else", 4, RTT_KEY_WORD);
+        result = g_dec_instruction_print(expr->false_branch, buffer, result, output);
+    }
 
+    return result;
 
 }
diff --git a/src/decomp/instr/ite.h b/src/decomp/instr/ite.h
index cff073a..e53abe8 100644
--- a/src/decomp/instr/ite.h
+++ b/src/decomp/instr/ite.h
@@ -52,6 +52,9 @@ typedef struct _GITEInstructionClass GITEInstructionClass;
 /* Indique le type défini pour un aiguillage du flux d'exécution. */
 GType g_ite_instruction_get_type(void);
 
+/* Détermine le corps des différentes branches possibles. */
+void g_ite_instruction_set_branches(GITEInstruction *, GDecInstruction *, GDecInstruction *);
+
 /* Exprime un aiguillage du flux en fonction d'une condition. */
 GDecInstruction *g_ite_instruction_new(GDecExpression *, vmpa_t, vmpa_t);
 
diff --git a/src/decomp/instruction-int.h b/src/decomp/instruction-int.h
index 2721b7f..9b29162 100644
--- a/src/decomp/instruction-int.h
+++ b/src/decomp/instruction-int.h
@@ -31,8 +31,11 @@
 
 
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+typedef void (* dec_instr_visit_fc) (GDecInstruction *, process_decomp_fc, void *, bool);
+
 /* Imprime pour l'écran un version humaine d'une instruction. */
-typedef void (* dec_instr_print_fc) (GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+typedef GBufferLine * (* dec_instr_print_fc) (const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 /* Définition d'une instruction décompilée (instance) */
@@ -44,6 +47,7 @@ struct _GDecInstruction
 
     vmpa_t address;                         /* Position associée           */
 
+    dec_instr_visit_fc visit;               /* Visite des instructions     */
     dec_instr_print_fc print;               /* Impression pour à l'écran   */
 
 };
diff --git a/src/decomp/instruction.c b/src/decomp/instruction.c
index c48ac7b..2d42e71 100644
--- a/src/decomp/instruction.c
+++ b/src/decomp/instruction.c
@@ -79,6 +79,35 @@ 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.                      *
+*                                                                             *
+*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_dec_instruction_visit(GDecInstruction *instr, process_decomp_fc process, void *data, bool order)
+{
+    if (order)
+        process(instr, data);
+
+    if (instr->visit)
+        instr->visit(instr, process, data, order);
+
+    if (!order)
+        process(instr, data);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr  = instruction à transcrire en version humaine.        *
 *                buffer = tampon où doit se réaliser l'insertion.             *
 *                line   = ligne d'impression prête à emploi ou NULL.          *
@@ -92,12 +121,9 @@ static void g_dec_instruction_init(GDecInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-void g_dec_instruction_print(const GDecInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+GBufferLine *g_dec_instruction_print(const GDecInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
-    if (line == NULL)
-        line = g_code_buffer_append_new_line_fixme(buffer);   /* FIXME : n° de ligne */
-
-    instr->print(instr, buffer, line, output);
+    return instr->print(instr, buffer, line, output);
 
 }
 
diff --git a/src/decomp/instruction.h b/src/decomp/instruction.h
index d8fe46c..810be79 100644
--- a/src/decomp/instruction.h
+++ b/src/decomp/instruction.h
@@ -48,11 +48,18 @@ typedef struct _GDecInstruction GDecInstruction;
 typedef struct _GDecInstructionClass GDecInstructionClass;
 
 
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+typedef void (* process_decomp_fc) (GDecInstruction *, 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);
+
 /* Imprime pour l'écran un version humaine d'une expression. */
-void g_dec_instruction_print(const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+GBufferLine *g_dec_instruction_print(const GDecInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
 
 
diff --git a/src/decomp/lang/java.c b/src/decomp/lang/java.c
index ae7fb70..f4466a5 100644
--- a/src/decomp/lang/java.c
+++ b/src/decomp/lang/java.c
@@ -84,6 +84,12 @@ static void g_java_output_start_routine_body(GJavaOutput *, GCodeBuffer *, GBuff
 /* Termine la définition du corps d'une routine. */
 static void g_java_output_end_routine_body(GJavaOutput *, GCodeBuffer *);
 
+/* Commence la définition d'un bloc de code. */
+static GBufferLine *g_java_output_start_code_block(GJavaOutput *, GCodeBuffer *, GBufferLine *, size_t);
+
+/* Termine la définition d'un bloc de code. */
+static GBufferLine *g_java_output_end_code_block(GJavaOutput *, GCodeBuffer *, GBufferLine *, size_t);
+
 
 
 /* Indique le type défini pour une sortie en langage Java. */
@@ -142,6 +148,9 @@ static void g_java_output_init(GJavaOutput *output)
     lang->start_routine_body = (lgbufln_fc)g_java_output_start_routine_body;
     lang->end_routine_body = (lgbuf_fc)g_java_output_end_routine_body;
 
+    lang->start_code_block = (rlgbuflnsz_fc)g_java_output_start_code_block;
+    lang->end_code_block = (rlgbuflnsz_fc)g_java_output_end_code_block;
+
 }
 
 
@@ -465,11 +474,12 @@ static void g_java_output_end_routine_prototype(GJavaOutput *output, GCodeBuffer
 
 static void g_java_output_start_routine_body(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line)
 {
+    /*
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 2, RTT_HOOK);
+    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK);
 
     g_code_buffer_inc_indentation(buffer);
-
+    */
 }
 
 
@@ -489,11 +499,79 @@ static void g_java_output_start_routine_body(GJavaOutput *output, GCodeBuffer *b
 static void g_java_output_end_routine_body(GJavaOutput *output, GCodeBuffer *buffer)
 {
     GBufferLine *line;                      /* Nouvelle ligne à constituer */
-
+    /*
     g_code_buffer_dec_indentation(buffer);
 
     line = g_code_buffer_append_new_line_fixme(buffer);
 
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK);
+    */
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
+*                buffer = tampon de sortie à disposition.                     *
+*                line   = ligne contenant le prototype de la routine traitée. *
+*                count  = nombre d'éléments du bloc.                          *
+*                                                                             *
+*  Description : Commence la définition d'un bloc de code.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_java_output_start_code_block(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count)
+{
+    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */
+
+    if (count > 1)
+    {
+        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+        g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK);
+    }
+
+    g_code_buffer_inc_indentation(buffer);
+
+    result = g_code_buffer_append_new_line_fixme(buffer);   /* FIXME : n° de ligne */
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
+*                buffer = tampon de sortie à disposition.                     *
+*                line   = ligne contenant le prototype de la routine traitée. *
+*                count  = nombre d'éléments du bloc.                          *
+*                                                                             *
+*  Description : Termine la définition d'un bloc de code.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_java_output_end_code_block(GJavaOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count)
+{
+    GBufferLine *result;                    /* Nouvelle ligne à constituer */
+
+    g_code_buffer_dec_indentation(buffer);
+
+    result = g_code_buffer_append_new_line_fixme(buffer);
+
+    if (count > 1)
+    {
+        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK);
+        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+    }
+
+    return result;
 
 }
diff --git a/src/decomp/output-int.h b/src/decomp/output-int.h
index 6c5f588..8ee7dd4 100644
--- a/src/decomp/output-int.h
+++ b/src/decomp/output-int.h
@@ -50,6 +50,11 @@ typedef void (* lgbuf_fc) (GLangOutput *, GCodeBuffer *);
 /* Xxx. */
 typedef void (* lgbufln_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *);
 
+/* Xxx. */
+typedef GBufferLine * (* rlgbufln_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *);
+
+/* Xxx. */
+typedef GBufferLine * (* rlgbuflnsz_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *, size_t);
 
 
 /* Sortie selon un langage de programmation (instance) */
@@ -73,7 +78,8 @@ struct _GLangOutput
     lgbufln_fc end_routine_proto;           /* Fin de prototype            */
     lgbufln_fc start_routine_body;          /* Début de définition         */
     lgbuf_fc end_routine_body;              /* Fin de définition de corps  */
-
+    rlgbuflnsz_fc start_code_block;         /* Début de définition         */
+    rlgbuflnsz_fc end_code_block;           /* Fin de définition de corps  */
 };
 
 
diff --git a/src/decomp/output.c b/src/decomp/output.c
index fd10921..648dddc 100644
--- a/src/decomp/output.c
+++ b/src/decomp/output.c
@@ -373,3 +373,61 @@ void g_lang_output_end_routine_body(GLangOutput *output, GCodeBuffer *buffer)
         output->end_routine_body(output, buffer);
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
+*                buffer = tampon de sortie à disposition.                     *
+*                line   = ligne contenant le prototype de la routine traitée. *
+*                count  = nombre d'éléments du bloc.                          *
+*                                                                             *
+*  Description : Commence la définition d'un bloc de code.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_lang_output_start_code_block(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count)
+{
+    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */
+
+    if (output->start_code_block != NULL)
+        result = output->start_code_block(output, buffer, line, count);
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
+*                buffer = tampon de sortie à disposition.                     *
+*                line   = ligne contenant le prototype de la routine traitée. *
+*                count  = nombre d'éléments du bloc.                          *
+*                                                                             *
+*  Description : Termine la définition d'un bloc de code.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_lang_output_end_code_block(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count)
+{
+    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */
+
+    if (output->end_code_block != NULL)
+        result = output->end_code_block(output, buffer, line, count);
+    else
+        result = NULL;
+
+    return result;
+
+}
diff --git a/src/decomp/output.h b/src/decomp/output.h
index f9ccd1d..dc81a98 100644
--- a/src/decomp/output.h
+++ b/src/decomp/output.h
@@ -99,6 +99,11 @@ void g_lang_output_start_routine_body(GLangOutput *, GCodeBuffer *, GBufferLine
 /* Termine la définition du corps d'une routine. */
 void g_lang_output_end_routine_body(GLangOutput *, GCodeBuffer *);
 
+/* Commence la définition d'un bloc de code. */
+GBufferLine *g_lang_output_start_code_block(GLangOutput *, GCodeBuffer *, GBufferLine *, size_t);
+
+/* Termine la définition d'un bloc de code. */
+GBufferLine *g_lang_output_end_code_block(GLangOutput *, GCodeBuffer *, GBufferLine *, size_t);
 
 
 
-- 
cgit v0.11.2-87-g4458