From 02c2cf555953f335a825e34c869c9999668fd42c Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 24 Feb 2013 11:09:36 +0000
Subject: Refined comparisons decompilation and fixed some bugs.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@340 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                        |  45 ++++++
 src/analysis/decomp/Makefile.am  |   1 +
 src/analysis/decomp/cmerge.c     | 135 +++++++++++++++++
 src/analysis/decomp/cmerge.h     |  37 +++++
 src/analysis/decomp/decompiler.c |   7 +-
 src/arch/dalvik/decomp/if.c      |  29 ++--
 src/decomp/expr/Makefile.am      |   1 +
 src/decomp/expr/block.c          |  27 ++++
 src/decomp/expr/block.h          |   3 +
 src/decomp/expr/comp.c           | 311 +++++++++++++++++++++++++++++++++++++++
 src/decomp/expr/comp.h           |  60 ++++++++
 src/decomp/expr/cond.c           | 287 +++++++++++++++++++++++++++++++-----
 src/decomp/expr/cond.h           |  18 ++-
 src/decomp/expression-int.h      |   7 +
 src/decomp/expression.c          |  63 +++++++-
 src/decomp/expression.h          |   5 +-
 src/decomp/instr/ite.c           |  57 ++++++-
 src/decomp/instr/ite.h           |   9 +-
 src/decomp/lang/java.c           |  77 +++++++++-
 src/decomp/output-int.h          |  13 +-
 src/decomp/output.c              |  53 ++++++-
 src/decomp/output.h              |  30 +++-
 22 files changed, 1199 insertions(+), 76 deletions(-)
 create mode 100644 src/analysis/decomp/cmerge.c
 create mode 100644 src/analysis/decomp/cmerge.h
 create mode 100644 src/decomp/expr/comp.c
 create mode 100644 src/decomp/expr/comp.h

diff --git a/ChangeLog b/ChangeLog
index 918e55a..0086536 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+13-02-24  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/decomp/cmerge.c:
+	* src/analysis/decomp/cmerge.h:
+	New entries: begin to merge conditions when possible.
+
+	* src/analysis/decomp/decompiler.c:
+	Disable the broken decompilation.
+
+	* src/analysis/decomp/Makefile.am:
+	Add the 'cmerge.[ch]' files to libanalysisdecomp_la_SOURCES.
+
+	* src/arch/dalvik/decomp/if.c:
+	Fix a bug for xxZ opcodes.
+
+	* src/decomp/expr/block.c:
+	* src/decomp/expr/block.h:
+	Provide a given item of blocks.
+
+	* src/decomp/expr/comp.c:
+	* src/decomp/expr/comp.h:
+	New entries: define comparisons.
+
+	* src/decomp/expr/cond.c:
+	* src/decomp/expr/cond.h:
+	Update code using the new comparison expressions.
+
+	* src/decomp/expression.c:
+	* src/decomp/expression.h:
+	* src/decomp/expression-int.h:
+	Handle the need of negating expressions for conditions.
+
+	* src/decomp/expr/Makefile.am:
+	Add the 'comp.[ch]' files to libdecompexpr_la_SOURCES.
+
+	* src/decomp/instr/ite.c:
+	* src/decomp/instr/ite.h:
+	Update code.
+
+	* src/decomp/lang/java.c:
+	* src/decomp/output.c:
+	* src/decomp/output.h:
+	* src/decomp/output-int.h:
+	Extend the kinds of output signs.
+
 13-02-10  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/disassembler.c:
diff --git a/src/analysis/decomp/Makefile.am b/src/analysis/decomp/Makefile.am
index 27388d6..0e3ffb4 100755
--- a/src/analysis/decomp/Makefile.am
+++ b/src/analysis/decomp/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libanalysisdecomp.la
 
 libanalysisdecomp_la_SOURCES =			\
+	cmerge.h cmerge.c					\
 	decompiler.h decompiler.c			\
 	il.h il.c							\
 	reduce.h reduce.c
diff --git a/src/analysis/decomp/cmerge.c b/src/analysis/decomp/cmerge.c
new file mode 100644
index 0000000..9838531
--- /dev/null
+++ b/src/analysis/decomp/cmerge.c
@@ -0,0 +1,135 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * cmerge.c - fusion des conditions successives
+ *
+ * Copyright (C) 2013 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 "cmerge.h"
+
+
+#include "../../decomp/expr/block.h"
+#include "../../decomp/expr/comp.h"
+#include "../../decomp/expr/cond.h"
+#include "../../decomp/instr/ite.h"
+
+
+
+/* Recherche des conditions successives pouvant être fusionnées. */
+static bool track_branch_conditions(GDecInstruction *, GDecInstruction *, DecInstrVisitFlags, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr  = instruction visitée.                                *
+*                parent = instruction parente.                                *
+*                flags  = moments des appels réalisés en retour.              *
+*                data   = adresse non utilisée ici.                           *
+*                                                                             *
+*  Description : Recherche des conditions successives pouvant être fusionnées.*
+*                                                                             *
+*  Retour      : true afin d'aller jusqu'au terme du parcours.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool track_branch_conditions(GDecInstruction *instr, GDecInstruction *parent, DecInstrVisitFlags flags, void *data)
+{
+    GDecInstruction *true_branch;           /* Branche 'vrai'              */
+    GDecInstruction *false_branch;          /* Branche 'faux'              */
+    GDecInstruction *first;                 /* Première sous-instruction   */
+    GCondExpression *sub_cond;              /* Expression conditionnelle   */
+    GCondExpression *top_cond;              /* Expression conditionnelle   */
+
+    if (!G_IS_ITE_INSTRUCTION(instr))
+        goto tbc_done;
+
+    g_ite_instruction_get_branches(G_ITE_INSTRUCTION(instr), &true_branch, &false_branch);
+    if (false_branch != NULL) goto tbc_done;
+
+    /* count(block) == 1 */
+
+    first = g_expr_block_get_item(G_EXPR_BLOCK(true_branch), 0);
+    if (!G_IS_ITE_INSTRUCTION(first)) goto tbc_done;
+
+    printf("got one!\n");
+
+    /* Récupération des informations inférieures */
+
+    sub_cond = g_ite_instruction_get_condition(G_ITE_INSTRUCTION(first));
+    g_object_ref(G_OBJECT(sub_cond));
+
+    g_ite_instruction_get_branches(G_ITE_INSTRUCTION(first), &true_branch, &false_branch);
+    if (true_branch != NULL) g_object_ref(G_OBJECT(true_branch));
+    if (false_branch != NULL) g_object_ref(G_OBJECT(false_branch));
+
+    /* Reconstitution d'une nouvelle instruction */
+
+    top_cond = g_ite_instruction_get_condition(G_ITE_INSTRUCTION(instr));
+
+    //g_cond_expression_add_condition(top_cond, sub_cond, COT_AND);
+
+    //g_ite_instruction_set_branches(G_ITE_INSTRUCTION(instr), true_branch, false_branch);
+
+
+
+
+    printf("got one!\n");
+
+    /*
+GDecExpression *g_ite_instruction_get_condition(const GITEInstruction *instr)
+
+
+
+GDecExpression *g_cond_expression_get_expression(const GCondExpression *cond)
+
+
+void g_cond_expression_set_expression(GCondExpression *cond, GDecExpression *exp)
+    */
+
+
+ tbc_done:
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instructions à traiter.                              *
+*                                                                             *
+*  Description : Fusionne les conditions qui s'enchaînent.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void merge_lonely_conditions(GDecInstruction *instr)
+{
+    return;
+
+    g_dec_instruction_visit(instr, (dec_instr_visitor_cb)track_branch_conditions,
+                            DVF_EXIT, NULL);
+
+}
diff --git a/src/analysis/decomp/cmerge.h b/src/analysis/decomp/cmerge.h
new file mode 100644
index 0000000..0b556c6
--- /dev/null
+++ b/src/analysis/decomp/cmerge.h
@@ -0,0 +1,37 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * cmerge.h - prototypes pour la fusion des conditions successives
+ *
+ * Copyright (C) 2013 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_CMERGE_H
+#define _ANALYSIS_DECOMP_CMERGE_H
+
+
+#include "../../decomp/instruction.h"
+
+
+
+/* Fusionne les conditions qui s'enchaînent. */
+void merge_lonely_conditions(GDecInstruction *);
+
+
+
+#endif  /* _ANALYSIS_DECOMP_CMERGE_H */
diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c
index c36811d..89f9d49 100644
--- a/src/analysis/decomp/decompiler.c
+++ b/src/analysis/decomp/decompiler.c
@@ -32,6 +32,7 @@
 #include <i18n.h>
 
 
+#include "cmerge.h"
 #include "il.h"
 #include "reduce.h"
 #include "../../decomp/output.h"
@@ -184,7 +185,9 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c
         //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context);
 
 
-        reduce_used_variables(dinstrs);
+        //merge_lonely_conditions(dinstrs);
+
+        /////reduce_used_variables(dinstrs);
 
         
         g_expr_block_set_border_behavior(G_EXPR_BLOCK(dinstrs), BBB_FORCE_ON);
@@ -228,7 +231,7 @@ GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *fi
 
     build_decomp_prologue(result, filename);
 
-    prepare_all_routines_for_decomp(binary, filename);
+    //prepare_all_routines_for_decomp(binary, filename);
 
 
 
diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c
index f7591b9..c82413d 100644
--- a/src/arch/dalvik/decomp/if.c
+++ b/src/arch/dalvik/decomp/if.c
@@ -25,6 +25,7 @@
 
 
 #include "../instruction.h"
+#include "../../../decomp/expr/comp.h"
 #include "../../../decomp/expr/cond.h"
 #include "../../../decomp/expr/immediate.h"
 #include "../../../decomp/instr/ite.h"
@@ -53,7 +54,8 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *op2;                   /* Second opérande utilisé     */
     vmpa_t jmp;                             /* Adresse de saut             */
-    GDecInstruction *cond;                  /* Comparaison à restituer     */
+    GDecInstruction *comp;                  /* Comparaison à restituer     */
+    GDecInstruction *cond;                  /* Transformation en condition */
 
     switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr)))
     {
@@ -91,8 +93,9 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte
     operand = g_arch_instruction_get_operand(instr, 2);
     jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/
 
-    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);
+    comp = g_comp_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2));
+    cond = g_cond_expression_new(comp);
+    result = g_ite_instruction_new(cond, jmp, jmp);
 
     return result;
 
@@ -122,26 +125,27 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *op2;                   /* Second opérande utilisé     */
     vmpa_t jmp;                             /* Adresse de saut             */
-    GDecInstruction *cond;                  /* Comparaison à restituer     */
+    GDecInstruction *comp;                  /* Comparaison à restituer     */
+    GDecInstruction *cond;                  /* Transformation en condition */
 
     switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr)))
     {
-        case DOP_IF_EQ:
+        case DOP_IF_EQZ:
             sign = CST_EQ;
             break;
-        case DOP_IF_NE:
+        case DOP_IF_NEZ:
             sign = CST_NE;
             break;
-        case DOP_IF_LT:
+        case DOP_IF_LTZ:
             sign = CST_LT;
             break;
-        case DOP_IF_GE:
+        case DOP_IF_GEZ:
             sign = CST_GE;
             break;
-        case DOP_IF_GT:
+        case DOP_IF_GTZ:
             sign = CST_GT;
             break;
-        case DOP_IF_LE:
+        case DOP_IF_LEZ:
             sign = CST_LE;
             break;
         default:
@@ -160,8 +164,9 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec
     operand = g_arch_instruction_get_operand(instr, 2);
     jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/
 
-    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);
+    comp = g_comp_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2));
+    cond = g_cond_expression_new(comp);
+    result = g_ite_instruction_new(cond, jmp, jmp);
 
     return result;
 
diff --git a/src/decomp/expr/Makefile.am b/src/decomp/expr/Makefile.am
index 483a1f3..3ff6cb5 100644
--- a/src/decomp/expr/Makefile.am
+++ b/src/decomp/expr/Makefile.am
@@ -8,6 +8,7 @@ libdecompexpr_la_SOURCES =				\
 	assign.h assign.c					\
 	block.h block.c						\
 	call.h call.c						\
+	comp.h comp.c						\
 	cond.h cond.c						\
 	immediate.h immediate.c				\
 	pseudo.h pseudo.c					\
diff --git a/src/decomp/expr/block.c b/src/decomp/expr/block.c
index 7c2387a..6b811f6 100644
--- a/src/decomp/expr/block.c
+++ b/src/decomp/expr/block.c
@@ -333,6 +333,33 @@ void g_expr_block_add_item(GExprBlock *block, GDecInstruction *item)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block = ensemble à consulter.                                *
+*                index = indice de l'instruction décompilée recherchée.       *
+*                                                                             *
+*  Description : Fournit une instruction décompilée donnée du conteneur.      *
+*                                                                             *
+*  Retour      : Instruction décompilée, ou NULL si l'indice n'est pas valide.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *g_expr_block_get_item(const GExprBlock *block, size_t index)
+{
+    GDecInstruction *result;                /* Elément à retourner         */
+
+    result = NULL;
+
+    if (index < block->count)
+        result = block->list[index];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block = ensemble à faire évoluer.                            *
 *                item  = nouvel élément à retirer de l'ensemble.              *
 *                                                                             *
diff --git a/src/decomp/expr/block.h b/src/decomp/expr/block.h
index b0788dd..92ac9f9 100644
--- a/src/decomp/expr/block.h
+++ b/src/decomp/expr/block.h
@@ -73,6 +73,9 @@ void g_expr_block_set_border_behavior(GExprBlock *, BlockBordeBehavior);
 /* Ajoute une instruction décompilée au conteneur existant. */
 void g_expr_block_add_item(GExprBlock *, GDecInstruction *);
 
+/* Fournit une instruction décompilée donnée du conteneur. */
+GDecInstruction *g_expr_block_get_item(const GExprBlock *, size_t);
+
 /* Supprime une instruction décompilée du conteneur existant. */
 void g_expr_block_delete_item(GExprBlock *, GDecInstruction *);
 
diff --git a/src/decomp/expr/comp.c b/src/decomp/expr/comp.c
new file mode 100644
index 0000000..3852aa8
--- /dev/null
+++ b/src/decomp/expr/comp.c
@@ -0,0 +1,311 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * comp.c - représentation des comparaisons
+ *
+ * Copyright (C) 2013 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 "comp.h"
+
+
+#include "../expression-int.h"
+
+
+
+/* Définition d'une comparaison binaire quelconque (instance) */
+struct _GCompExpression
+{
+    GDecExpression parent;                  /* A laisser en premier        */
+
+    GDecExpression *a;                      /* Premier élément à comparer  */
+    CompSignType sign;                      /* Méthode de comparaison      */
+    GDecExpression *b;                      /* Second élément à comparer   */
+
+};
+
+
+/* Définition d'une comparaison binaire quelconque (classe) */
+struct _GCompExpressionClass
+{
+    GDecExpressionClass parent;             /* A laisser en premier        */
+
+};
+
+
+
+/* Initialise la classe des comparaisons binaires quelconques. */
+static void g_comp_expression_class_init(GCompExpressionClass *);
+
+/* Initialise une instance de comparaison binaire quelconque. */
+static void g_comp_expression_init(GCompExpression *);
+
+/* Visite un ensemble hiérarchique d'instructions décompilées. */
+static bool g_comp_expression_visit(GCompExpression *, dec_instr_visitor_cb, DecInstrVisitFlags, void *);
+
+/* Remplace une instruction décompilée par une autre. */
+static bool g_comp_expression_replace(GCompExpression *, GDecInstruction *, GDecInstruction *);
+
+/* Imprime pour l'écran un version humaine d'une expression. */
+static GBufferLine *g_comp_expression_print(const GCompExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+
+/* Réalise une négation sur une expression décompilée. */
+static bool g_comp_expression_negate(GCompExpression *);
+
+
+
+/* Indique le type défini pour une comparaison binaire quelconque. */
+G_DEFINE_TYPE(GCompExpression, g_comp_expression, G_TYPE_DEC_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des comparaisons binaires quelconques.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_comp_expression_class_init(GCompExpressionClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de comparaison binaire quelconque.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_comp_expression_init(GCompExpression *expr)
+{
+    GDecInstruction *instr;                 /* Autre version de l'objet    */
+    GDecExpression *base;                   /* Autre version de l'objet    */
+
+    instr = G_DEC_INSTRUCTION(expr);
+
+    instr->visit = (dec_instr_visit_fc)g_comp_expression_visit;
+    instr->replace = (dec_instr_replace_fc)g_comp_expression_replace;
+    instr->print = (dec_instr_print_fc)g_comp_expression_print;
+
+    base = G_DEC_EXPRESSION(expr);
+
+    base->negate = (dec_expr_negate_fc)g_comp_expression_negate;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a    = second élément à comparer.                            *
+*                sign = choix de la méthode de comparaison.                   *
+*                b    = second élément à comparer.                            *
+*                                                                             *
+*  Description : Exprime une comparaison binaire quelconque.                  *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecExpression *g_comp_expression_new(GDecExpression *a, CompSignType sign, GDecExpression *b)
+{
+    GCompExpression *result;              /* Expression à retourner      */
+
+    result = g_object_new(G_TYPE_COMP_EXPRESSION, NULL);
+
+    result->a = a;
+    result->sign = sign;
+    result->b = b;
+
+    return G_DEC_EXPRESSION(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_comp_expression_visit(GCompExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->a), G_DEC_INSTRUCTION(expr),
+                                      callback, flags, data);
+
+    if (result)
+        result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->b), G_DEC_INSTRUCTION(expr),
+                                          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_comp_expression_replace(GCompExpression *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.          *
+*                output = langage de programmation de sortie.                 *
+*                                                                             *
+*  Description : Imprime pour l'écran un version humaine d'une expression.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_comp_expression_print(const GCompExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+{
+    GBufferLine *result;                    /* Ligne à retourner           */
+
+    result = line;
+
+    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a),
+                                     buffer, result, 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;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = instance à traiter.                                   *
+*                                                                             *
+*  Description : Réalise une négation sur une expression décompilée.          *
+*                                                                             *
+*  Retour      : true si la négation a été gérée, false sinon.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_comp_expression_negate(GCompExpression *expr)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    switch (expr->sign)
+    {
+        case CST_EQ:
+            expr->sign = CST_NE;
+            break;
+        case CST_NE:
+            expr->sign = CST_EQ;
+            break;
+        case CST_LT:
+            expr->sign = CST_GE;
+            break;
+        case CST_GE:
+            expr->sign = CST_LT;
+            break;
+        case CST_GT:
+            expr->sign = CST_LE;
+            break;
+        case CST_LE:
+            expr->sign = CST_GT;
+            break;
+        default:
+            result = false;
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/src/decomp/expr/comp.h b/src/decomp/expr/comp.h
new file mode 100644
index 0000000..8599aa0
--- /dev/null
+++ b/src/decomp/expr/comp.h
@@ -0,0 +1,60 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * comp.h - prototypes pour la représentation des comparaisons
+ *
+ * Copyright (C) 2013 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 _DECOMP_EXPR_COMP_H
+#define _DECOMP_EXPR_COMP_H
+
+
+#include <glib-object.h>
+
+
+#include "../expression.h"
+#include "../output.h"
+
+
+
+#define G_TYPE_COMP_EXPRESSION               g_comp_expression_get_type()
+#define G_COMP_EXPRESSION(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_comp_expression_get_type(), GCompExpression))
+#define G_IS_COMP_EXPRESSION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_comp_expression_get_type()))
+#define G_COMP_EXPRESSION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_COMP_EXPRESSION, GCompExpressionClass))
+#define G_IS_COMP_EXPRESSION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_COMP_EXPRESSION))
+#define G_COMP_EXPRESSION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_COMP_EXPRESSION, GCompExpressionClass))
+
+
+
+/* Définition d'une comparaison binaire quelconque (instance) */
+typedef struct _GCompExpression GCompExpression;
+
+/* Définition d'une comparaison binaire quelconque (classe) */
+typedef struct _GCompExpressionClass GCompExpressionClass;
+
+
+/* Indique le type défini pour une comparaison binaire quelconque. */
+GType g_comp_expression_get_type(void);
+
+/* Exprime une comparaison binaire quelconque. */
+GDecExpression *g_comp_expression_new(GDecExpression *, CompSignType, GDecExpression *);
+
+
+
+#endif  /* _DECOMP_EXPR_COMP_H */
diff --git a/src/decomp/expr/cond.c b/src/decomp/expr/cond.c
index fab2c17..c776059 100644
--- a/src/decomp/expr/cond.c
+++ b/src/decomp/expr/cond.c
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * cond.c - représentation des conditions
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -24,6 +24,9 @@
 #include "cond.h"
 
 
+#include <malloc.h>
+
+
 #include "../expression-int.h"
 
 
@@ -33,9 +36,17 @@ struct _GCondExpression
 {
     GDecExpression parent;                  /* A laisser en premier        */
 
-    GDecExpression *a;                      /* Premier élément à comparer  */
-    CompSignType sign;                      /* Méthode de comparaison      */
-    GDecExpression *b;                      /* Second élément à comparer   */
+    CondOperatorType operator;              /* Opérateur de la liste       */
+
+    union
+    {
+        GDecExpression *exp;                /* Expression analysée de base */
+        struct
+        {
+            GCondExpression **conds;        /* Liste d'expressions         */
+            size_t count;                   /* Taille de cette liste       */
+        };
+    };
 
 };
 
@@ -64,6 +75,9 @@ static bool g_cond_expression_replace(GCondExpression *, GDecInstruction *, GDec
 /* Imprime pour l'écran un version humaine d'une expression. */
 static GBufferLine *g_cond_expression_print(const GCondExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
 
+/* Réalise une négation sur une expression décompilée. */
+static bool g_cond_expression_negate(GCondExpression *);
+
 
 
 /* Indique le type défini pour une condition binaire quelconque. */
@@ -90,7 +104,7 @@ static void g_cond_expression_class_init(GCondExpressionClass *klass)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : expr = instance à initialiser.                               *
+*  Paramètres  : cond = instance à initialiser.                               *
 *                                                                             *
 *  Description : Initialise une instance de condition binaire quelconque.     *
 *                                                                             *
@@ -100,24 +114,29 @@ static void g_cond_expression_class_init(GCondExpressionClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_cond_expression_init(GCondExpression *expr)
+static void g_cond_expression_init(GCondExpression *cond)
 {
     GDecInstruction *instr;                 /* Autre version de l'objet    */
+    GDecExpression *expr;                   /* Autre version de l'objet    */
 
-    instr = G_DEC_INSTRUCTION(expr);
+    instr = G_DEC_INSTRUCTION(cond);
 
     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;
 
+    expr = G_DEC_EXPRESSION(cond);
+
+    expr->negate = (dec_expr_negate_fc)g_cond_expression_negate;
+
+    cond->operator = COT_NONE;
+
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : a    = second élément à comparer.                            *
-*                sign = choix de la méthode de comparaison.                   *
-*                b    = second élément à comparer.                            *
+*  Paramètres  : exp = expression sur laquelle repose la condition.           *
 *                                                                             *
 *  Description : Exprime une condition binaire quelconque.                    *
 *                                                                             *
@@ -127,17 +146,15 @@ static void g_cond_expression_init(GCondExpression *expr)
 *                                                                             *
 ******************************************************************************/
 
-GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDecExpression *b)
+GDecExpression *g_cond_expression_new(GDecExpression *exp)
 {
     GCondExpression *result;              /* Expression à retourner      */
 
     result = g_object_new(G_TYPE_COND_EXPRESSION, NULL);
 
-    result->a = a;
-    result->sign = sign;
-    result->b = b;
+    result->exp = exp;
 
-    return G_DEC_INSTRUCTION(result);
+    return G_DEC_EXPRESSION(result);
 
 }
 
@@ -160,14 +177,23 @@ GDecInstruction *g_cond_expression_new(GDecExpression *a, CompSignType sign, GDe
 static bool g_cond_expression_visit(GCondExpression *expr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data)
 {
     bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
 
-    result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->a), G_DEC_INSTRUCTION(expr),
-                                      callback, flags, data);
-
-    if (result)
-        result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->b), G_DEC_INSTRUCTION(expr),
+    if (expr->operator == COT_NONE)
+        result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->exp), G_DEC_INSTRUCTION(expr),
                                           callback, flags, data);
 
+    else
+    {
+        result = true;
+
+        for (i = 0; i < expr->count && result; i++)
+            result = _g_dec_instruction_visit(G_DEC_INSTRUCTION(expr->conds[i]),
+                                              G_DEC_INSTRUCTION(expr),
+                                              callback, flags, data);
+
+    }
+
     return result;
 
 }
@@ -190,30 +216,44 @@ static bool g_cond_expression_visit(GCondExpression *expr, dec_instr_visitor_cb
 static bool g_cond_expression_replace(GCondExpression *expr, GDecInstruction *old, GDecInstruction *new)
 {
     bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
 
-    if (expr->a == G_DEC_EXPRESSION(old))
+    if (expr->operator == COT_NONE)
     {
-        g_object_unref(G_OBJECT(expr->a));
-        g_object_ref(G_OBJECT(new));
-        expr->a = G_DEC_EXPRESSION(new);
+        if (expr->exp == G_DEC_EXPRESSION(old))
+        {
+            g_object_unref(G_OBJECT(expr->exp));
+            g_object_ref(G_OBJECT(new));
+            expr->exp = G_DEC_EXPRESSION(new);
 
-        result = true;
+            result = true;
+
+        }
+        else
+            result = g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->exp), old, new);
 
     }
     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 = false;
 
-        result = true;
+        for (i = 0; i < expr->count; i++)
+        {
+            if (expr->conds[i] == G_COND_EXPRESSION(old))
+            {
+                g_object_unref(G_OBJECT(expr->conds[i]));
+                g_object_ref(G_OBJECT(new));
+                expr->conds[i] = G_COND_EXPRESSION(new);
+
+                result = true;
+
+            }
+            else
+                result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->conds[i]), old, new);
+
+        }
 
     }
-    else
-        result |= g_dec_instruction_replace(G_DEC_INSTRUCTION(expr->b), old, new);
 
     return result;
 
@@ -238,15 +278,184 @@ static bool g_cond_expression_replace(GCondExpression *expr, GDecInstruction *ol
 static GBufferLine *g_cond_expression_print(const GCondExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
     GBufferLine *result;                    /* Ligne à retourner           */
+    size_t i;                               /* Boucle de parcours          */
 
-    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->a),
-                                     buffer, line, output);
+    result = g_lang_output_encapsulate_condition(output, buffer, line, true);
 
-    g_lang_output_write_comp_sign(output, result, expr->sign);
+    if (expr->operator == COT_NONE)
+        result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->exp),
+                                         buffer, result, output);
 
-    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->b),
-                                     buffer, result, output);
+    else
+        for (i = 0; i < expr->count; i++)
+        {
+            if (i > 0)
+                g_lang_output_write_cond_operator(output, result, expr->operator);
+
+            result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->conds[i]),
+                                             buffer, result, output);
+
+        }
+
+    result = g_lang_output_encapsulate_condition(output, buffer, result, false);
 
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cond = instance à traiter.                                   *
+*                                                                             *
+*  Description : Réalise une négation sur une expression décompilée.          *
+*                                                                             *
+*  Retour      : true si la négation a été gérée, false sinon.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_cond_expression_negate(GCondExpression *cond)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    if (cond->operator == COT_NONE)
+        g_dec_expression_negate(cond->exp);
+
+    else
+    {
+        cond->operator = (cond->operator == COT_AND ? COT_OR : COT_AND);
+
+        for (i = 0; i < cond->count; i++)
+            g_dec_expression_negate(G_DEC_EXPRESSION(cond->conds[i]));
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cond = instance à consulter.                                 *
+*                                                                             *
+*  Description : Fournit l'opération logique entre les comparaisons.          *
+*                                                                             *
+*  Retour      : Opération liant les différentes parties, ou COT_NONE.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+CondOperatorType g_cond_expression_get_operator(const GCondExpression *cond)
+{
+    return cond->operator;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cond = instance à consulter.                                 *
+*                                                                             *
+*  Description : Fournit l'expression d'une condition.                        *
+*                                                                             *
+*  Retour      : Expression sur laquelle repose la condition.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecExpression *g_cond_expression_get_expression(const GCondExpression *cond)
+{
+    return cond->exp;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cond = instance à modifier.                                  *
+*                exp  = expression sur laquelle repose la condition.          *
+*                                                                             *
+*  Description : Définit l'expression d'une condition.                        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_cond_expression_set_expression(GCondExpression *cond, GDecExpression *exp)
+{
+    if (cond->exp != NULL)
+        g_object_unref(G_OBJECT(cond->exp));
+
+    cond->exp = exp;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : cond  = instance à compléter.                                *
+*                extra = condition à rajouter.                                *
+*                op    = lien avec le reste de la condition.                  *
+*                                                                             *
+*  Description : Etend l'expression d'une condition.                          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_cond_expression_add_condition(GCondExpression *cond, GCondExpression *extra, CondOperatorType op)
+{
+    GCondExpression *existing;              /* Expr. première revalorisée  */
+
+    if (cond->operator == COT_NONE)
+    {
+        existing = G_COND_EXPRESSION(g_cond_expression_new(cond->exp));
+        goto gceac_replace_existing;
+    }
+    else
+    {
+        if (cond->operator == op)
+        {
+            cond->conds = (GCondExpression **)calloc(++cond->count, sizeof(GCondExpression));
+            cond->conds[cond->count - 1] = extra;
+        }
+        else
+        {
+            existing = G_COND_EXPRESSION(g_cond_expression_new(NULL));
+
+            existing->operator = cond->operator;
+            existing->conds = cond->conds;
+            existing->count = cond->count;
+
+            goto gceac_replace_existing;
+
+        }
+
+    }
+
+ gceac_done:
+
+    return;
+
+ gceac_replace_existing:
+
+    cond->operator = op;
+
+    cond->conds = (GCondExpression **)calloc(2, sizeof(GCondExpression));
+    cond->conds[0] = existing;
+    cond->conds[1] = extra;
+
+    cond->count = 2;
+
+    goto gceac_done;
+
+}
diff --git a/src/decomp/expr/cond.h b/src/decomp/expr/cond.h
index b6fd073..a4d1ee7 100644
--- a/src/decomp/expr/cond.h
+++ b/src/decomp/expr/cond.h
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * cond.h - prototypes pour la représentation des conditions
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -29,7 +29,7 @@
 
 
 #include "../expression.h"
-#include "../instruction.h"
+#include "../output.h"
 
 
 
@@ -53,7 +53,19 @@ typedef struct _GCondExpressionClass GCondExpressionClass;
 GType g_cond_expression_get_type(void);
 
 /* Exprime une condition binaire quelconque. */
-GDecInstruction *g_cond_expression_new(GDecExpression *, CompSignType, GDecExpression *);
+GDecExpression *g_cond_expression_new(GDecExpression *);
+
+/* Fournit l'opération logique entre les comparaisons. */
+CondOperatorType g_cond_expression_get_operator(const GCondExpression *);
+
+/* Fournit l'expression d'une condition. */
+GDecExpression *g_cond_expression_get_expression(const GCondExpression *);
+
+/* Définit l'expression d'une condition. */
+void g_cond_expression_set_expression(GCondExpression *, GDecExpression *);
+
+/* Etend l'expression d'une condition. */
+void g_cond_expression_add_condition(GCondExpression *, GCondExpression *, CondOperatorType);
 
 
 
diff --git a/src/decomp/expression-int.h b/src/decomp/expression-int.h
index dacd9b8..ba15ce3 100644
--- a/src/decomp/expression-int.h
+++ b/src/decomp/expression-int.h
@@ -30,11 +30,18 @@
 
 
 
+/* Réalise une négation sur une expression décompilée. */
+typedef bool (* dec_expr_negate_fc) (GDecExpression *);
+
+
 /* Définition d'une expression décompilée (instance) */
 struct _GDecExpression
 {
     GDecInstruction parent;                 /* A laisser en premier        */
 
+    dec_expr_negate_fc negate;              /* Négation de l'expression    */
+    dec_instr_print_fc original_print;      /* Eventuelle version négative */
+
 };
 
 
diff --git a/src/decomp/expression.c b/src/decomp/expression.c
index 82a2b4a..783f78f 100644
--- a/src/decomp/expression.c
+++ b/src/decomp/expression.c
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * expression.c - gestion des expressions décompilées
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -34,6 +34,9 @@ static void g_dec_expression_class_init(GDecExpressionClass *);
 /* Initialise une instance d'expression décompilée. */
 static void g_dec_expression_init(GDecExpression *);
 
+/* Imprime pour l'écran la négation d'une expression décompilée. */
+static GBufferLine *g_dec_expression_neg_print(const GDecExpression *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+
 
 
 /* Indique le type défini pour une expression décompilée. */
@@ -74,3 +77,61 @@ static void g_dec_expression_init(GDecExpression *expr)
 {
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  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.          *
+*                output = langage de programmation de sortie.                 *
+*                                                                             *
+*  Description : Imprime pour l'écran la négation d'une expression décompilée.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_dec_expression_neg_print(const GDecExpression *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+{
+    GBufferLine *result;                    /* Ligne à retourner           */
+
+    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD);
+
+    result = expr->original_print(G_DEC_INSTRUCTION(expr), buffer, line, output);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = instance à traiter.                                   *
+*                                                                             *
+*  Description : Réalise une négation sur une expression décompilée.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_dec_expression_negate(GDecExpression *expr)
+{
+    bool status;                            /* Réussite de l'opération ?   */
+
+    if (expr->negate != NULL)
+        status = expr->negate(expr);
+    else
+        status = false;
+
+    if (!status)
+    {
+        expr->original_print = G_DEC_INSTRUCTION(expr)->print;
+        G_DEC_INSTRUCTION(expr)->print = (dec_instr_print_fc)g_dec_expression_neg_print;
+    }
+
+}
diff --git a/src/decomp/expression.h b/src/decomp/expression.h
index 4a56c24..01eaa66 100644
--- a/src/decomp/expression.h
+++ b/src/decomp/expression.h
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * expression.h - prototypes pour la gestion des expressions décompilées
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -48,6 +48,9 @@ typedef struct _GDecExpressionClass GDecExpressionClass;
 /* Indique le type défini pour une expression décompilée. */
 GType g_dec_expression_get_type(void);
 
+/* Réalise une négation sur une expression décompilée. */
+void g_dec_expression_negate(GDecExpression *);
+
 
 
 #endif  /* _DECOMP_EXPRESSION_H */
diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c
index 60627a6..5cdeb87 100644
--- a/src/decomp/instr/ite.c
+++ b/src/decomp/instr/ite.c
@@ -33,9 +33,7 @@ struct _GITEInstruction
 {
     GDecInstruction parent;                 /* A laisser en premier        */
 
-    bool inverse;                           /* Condition inversée          */
-
-    GDecExpression *cond;                   /* Condition prise en compte   */
+    GCondExpression *cond;                  /* Condition prise en compte   */
 
     GDecInstruction *true_branch;           /* Condition vérifiée          */
     GDecInstruction *false_branch;          /* Condition non vérifiée      */
@@ -144,7 +142,7 @@ static void g_ite_instruction_init(GITEInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmpa_t if_false)
+GDecInstruction *g_ite_instruction_new(GCondExpression *cond, vmpa_t if_true, vmpa_t if_false)
 {
     GITEInstruction *result;              /* Expression à retourner      */
 
@@ -245,9 +243,6 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB
 
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD);
 
-    if (instr->inverse)
-        g_buffer_line_insert_text(line /* FIXME */, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD);
-
     result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->cond),
                                      buffer, line, output);
 
@@ -266,6 +261,25 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr = instruction fixant le choix de l'aiguillage.         *
+*                                                                             *
+*  Description : Fournit la condition régissant la suite de l'exécution.      *
+*                                                                             *
+*  Retour      : Condition mise en place.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GCondExpression *g_ite_instruction_get_condition(const GITEInstruction *instr)
+{
+    return instr->cond;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr        = 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.  *
@@ -280,10 +294,12 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeB
 
 void g_ite_instruction_set_branches(GITEInstruction *instr, GDecInstruction *true_branch, GDecInstruction *false_branch)
 {
+    if (instr->true_branch != NULL) g_object_unref(G_OBJECT(instr->true_branch));
+    if (instr->false_branch != NULL) g_object_unref(G_OBJECT(instr->false_branch));
 
     if (true_branch == NULL)
     {
-        instr->inverse = true;
+        g_dec_expression_negate(G_DEC_EXPRESSION(instr->cond));
 
         instr->true_branch = false_branch;
         instr->false_branch = true_branch;
@@ -296,3 +312,28 @@ void g_ite_instruction_set_branches(GITEInstruction *instr, GDecInstruction *tru
     }
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr        = instruction fixant le choix de l'aiguillage.  *
+*                true_branch  = instrs. si la condition est vérifiée. [OUT]   *
+*                false_branch = instrs. si la cond. n'est pas vérifiée. [OUT] *
+*                                                                             *
+*  Description : Fournit le corps des différentes branches possibles.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_ite_instruction_get_branches(const GITEInstruction *instr, GDecInstruction **true_branch, GDecInstruction **false_branch)
+{
+    if (true_branch != NULL)
+        *true_branch = instr->true_branch;
+
+    if (false_branch != NULL)
+        *false_branch = instr->false_branch;
+
+}
diff --git a/src/decomp/instr/ite.h b/src/decomp/instr/ite.h
index 7137452..91c18ae 100644
--- a/src/decomp/instr/ite.h
+++ b/src/decomp/instr/ite.h
@@ -30,6 +30,7 @@
 
 #include "../expression.h"
 #include "../instruction.h"
+#include "../expr/cond.h"
 
 
 
@@ -53,11 +54,17 @@ typedef struct _GITEInstructionClass GITEInstructionClass;
 GType g_ite_instruction_get_type(void);
 
 /* Exprime un aiguillage du flux en fonction d'une condition. */
-GDecInstruction *g_ite_instruction_new(GDecExpression *, vmpa_t, vmpa_t);
+GDecInstruction *g_ite_instruction_new(GCondExpression *, vmpa_t, vmpa_t);
+
+/* Fournit la condition régissant la suite de l'exécution. */
+GCondExpression *g_ite_instruction_get_condition(const GITEInstruction *);
 
 /* Détermine le corps des différentes branches possibles. */
 void g_ite_instruction_set_branches(GITEInstruction *, GDecInstruction *, GDecInstruction *);
 
+/* Fournit le corps des différentes branches possibles. */
+void g_ite_instruction_get_branches(const GITEInstruction *, GDecInstruction **, GDecInstruction **);
+
 
 
 #endif  /* _DECOMP_INSTR_ITE_H */
diff --git a/src/decomp/lang/java.c b/src/decomp/lang/java.c
index f4466a5..65383b0 100644
--- a/src/decomp/lang/java.c
+++ b/src/decomp/lang/java.c
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * java.c - sorties en langage Java
  *
- * Copyright (C) 2010-2012 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -66,6 +66,9 @@ static GBufferLine *g_java_output_write_comments(GJavaOutput *, GCodeBuffer *, c
 /* Imprime dans un tampon donné une méthode de comparaison. */
 static void g_java_output_write_comp_sign(GJavaOutput *, GBufferLine *, CompSignType);
 
+/* Imprime dans un tampon donné un opérateur logique. */
+static void g_java_output_write_cond_operator(GLangOutput *, GBufferLine *, CondOperatorType);
+
 /* Débute la définition d'une classe. */
 static GBufferLine *g_java_output_start_class(GJavaOutput *, GCodeBuffer *, const GDataType *);
 
@@ -90,6 +93,9 @@ static GBufferLine *g_java_output_start_code_block(GJavaOutput *, GCodeBuffer *,
 /* Termine la définition d'un bloc de code. */
 static GBufferLine *g_java_output_end_code_block(GJavaOutput *, GCodeBuffer *, GBufferLine *, size_t);
 
+/* Emballe une expression conditionelle. */
+static GBufferLine *g_java_output_encapsulate_condition(GLangOutput *, GCodeBuffer *, GBufferLine *, bool);
+
 
 
 /* Indique le type défini pour une sortie en langage Java. */
@@ -139,6 +145,7 @@ static void g_java_output_init(GJavaOutput *output)
     lang->write_comments = (write_comments_fc)g_java_output_write_comments;
 
     lang->comp_sign = (write_comp_sign_fc)g_java_output_write_comp_sign;
+    lang->cond_op = (write_cond_op_fc)g_java_output_write_cond_operator;
 
     lang->start_class = (rlgbuftp_fc)g_java_output_start_class;
     lang->end_class = (lgbuf_fc)g_java_output_end_class;
@@ -150,6 +157,7 @@ static void g_java_output_init(GJavaOutput *output)
 
     lang->start_code_block = (rlgbuflnsz_fc)g_java_output_start_code_block;
     lang->end_code_block = (rlgbuflnsz_fc)g_java_output_end_code_block;
+    lang->encaps_cond = (lo_buf_ln_bool_fc)g_java_output_encapsulate_condition;
 
 }
 
@@ -342,6 +350,42 @@ static void g_java_output_write_comp_sign(GJavaOutput *output, GBufferLine *line
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : output = encadrant de l'impression en langage de prog.       *
+*                line   = tampon de sortie à disposition.                     *
+*                op     = opérateur logique à imprimer.                       *
+*                                                                             *
+*  Description : Imprime dans un tampon donné un opérateur logique.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_java_output_write_cond_operator(GLangOutput *output, GBufferLine *line, CondOperatorType op)
+{
+    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+
+    switch (op)
+    {
+        case COT_AND:
+            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "&&", 2, RTT_SIGNS);
+            break;
+        case COT_OR:
+            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "||", 2, RTT_SIGNS);
+            break;
+        default:
+            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "??", 2, RTT_SIGNS);
+            break;
+    }
+
+    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
 *                buffer = tampon de sortie à disposition.                     *
 *                type   = désignation de la classe à définir.                 *
 *                                                                             *
@@ -575,3 +619,34 @@ static GBufferLine *g_java_output_end_code_block(GJavaOutput *output, GCodeBuffe
     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.*
+*                opening = précise si la condition débute ou se termine.      *
+*                                                                             *
+*  Description : Emballe une expression conditionelle.                        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_java_output_encapsulate_condition(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, bool opening)
+{
+    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */
+
+    result = line;
+
+    if (opening)
+        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "(", 1, RTT_HOOK);
+    else
+        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_HOOK);
+
+    return result;
+
+}
diff --git a/src/decomp/output-int.h b/src/decomp/output-int.h
index 8ee7dd4..95b891b 100644
--- a/src/decomp/output-int.h
+++ b/src/decomp/output-int.h
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * output-int.h - définitions internes pour les sorties en langage de programmation
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -38,6 +38,9 @@ typedef GBufferLine * (* write_comments_fc) (GLangOutput *, GCodeBuffer *, const
 /* Imprime dans un tampon donné une méthode de comparaison. */
 typedef void (* write_comp_sign_fc) (GLangOutput *, GBufferLine *, CompSignType);
 
+/* Imprime dans un tampon donné un opérateur logique. */
+typedef void (* write_cond_op_fc) (GLangOutput *, GBufferLine *, CondOperatorType);
+
 /* Débute la documentation d'une routine. */
 typedef GBufferLine * (* start_rtn_info_fc) (const GLangOutput *, GCodeBuffer *);
 
@@ -57,6 +60,11 @@ typedef GBufferLine * (* rlgbufln_fc) (GLangOutput *, GCodeBuffer *, GBufferLine
 typedef GBufferLine * (* rlgbuflnsz_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *, size_t);
 
 
+/* Xxx. */
+typedef GBufferLine * (* lo_buf_ln_bool_fc) (GLangOutput *, GCodeBuffer *, GBufferLine *, bool);
+
+
+
 /* Sortie selon un langage de programmation (instance) */
 struct _GLangOutput
 {
@@ -68,6 +76,7 @@ struct _GLangOutput
     write_comments_fc write_comments;       /* Commentaires sur une ligne  */
 
     write_comp_sign_fc comp_sign;           /* Méthde de comparaison       */
+    write_cond_op_fc cond_op;               /* Opérateur logique           */
 
     rlgbuftp_fc start_class;                /* Début de définition         */
     lgbuf_fc end_class;                     /* Fin de définition de classe */
@@ -80,6 +89,8 @@ struct _GLangOutput
     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  */
+    lo_buf_ln_bool_fc encaps_cond;          /* Emballe une condition       */
+
 };
 
 
diff --git a/src/decomp/output.c b/src/decomp/output.c
index 5689319..c358653 100644
--- a/src/decomp/output.c
+++ b/src/decomp/output.c
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * output.c - sorties en langage de programmation
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2013 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -206,6 +206,28 @@ void g_lang_output_write_comp_sign(GLangOutput *output, GBufferLine *line, CompS
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : output = encadrant de l'impression en langage de prog.       *
+*                line   = tampon de sortie à disposition.                     *
+*                op     = opérateur logique à imprimer.                       *
+*                                                                             *
+*  Description : Imprime dans un tampon donné un opérateur logique.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_lang_output_write_cond_operator(GLangOutput *output, GBufferLine *line, CondOperatorType op)
+{
+    if (output->cond_op != NULL)
+        output->cond_op(output, line, op);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
 *                buffer = tampon de sortie à disposition.                     *
 *                type   = désignation de la classe à définir.                 *
 *                                                                             *
@@ -430,3 +452,32 @@ GBufferLine *g_lang_output_end_code_block(GLangOutput *output, GCodeBuffer *buff
     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.*
+*                opening = précise si la condition débute ou se termine.      *
+*                                                                             *
+*  Description : Emballe une expression conditionelle.                        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBufferLine *g_lang_output_encapsulate_condition(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, bool opening)
+{
+    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */
+
+    if (output->encaps_cond != NULL)
+        result = output->encaps_cond(output, buffer, line, opening);
+    else
+        result = NULL;
+
+    return result;
+
+}
diff --git a/src/decomp/output.h b/src/decomp/output.h
index dc81a98..63f586a 100644
--- a/src/decomp/output.h
+++ b/src/decomp/output.h
@@ -63,20 +63,35 @@ GBufferLine *g_lang_output_write_comments(GLangOutput *, GCodeBuffer *, const ch
 /* Liste des signes binaires de comparaison */
 typedef enum _CompSignType
 {
-    CST_EQ,                                 /* == */
-    CST_NE,                                 /* != */
-    CST_LT,                                 /* < */
-    CST_GE,                                 /* >= */
-    CST_GT,                                 /* > */
-    CST_LE,                                 /* <= */
+    CST_EQ,                                 /* ==                          */
+    CST_NE,                                 /* !=                          */
+    CST_LT,                                 /* <                           */
+    CST_GE,                                 /* >=                          */
+    CST_GT,                                 /* >                           */
+    CST_LE,                                 /* <=                          */
 
     CST_COUNT
 
 } CompSignType;
 
+/* Liste des signes binaires de comparaison */
+typedef enum _CondOperatorType
+{
+    COT_NONE,                               /* pas de condition            */
+    COT_AND,                                /* &&                          */
+    COT_OR,                                 /* ||                          */
+
+    COT_COUNT
+
+} CondOperatorType;
+
+
 /* Imprime dans un tampon donné une méthode de comparaison. */
 void g_lang_output_write_comp_sign(GLangOutput *, GBufferLine *, CompSignType);
 
+/* Imprime dans un tampon donné un opérateur logique. */
+void g_lang_output_write_cond_operator(GLangOutput *, GBufferLine *, CondOperatorType);
+
 
 /* Débute la définition d'une classe. */
 GBufferLine *g_lang_output_start_class(GLangOutput *, GCodeBuffer *, const void *);
@@ -105,6 +120,9 @@ GBufferLine *g_lang_output_start_code_block(GLangOutput *, GCodeBuffer *, GBuffe
 /* Termine la définition d'un bloc de code. */
 GBufferLine *g_lang_output_end_code_block(GLangOutput *, GCodeBuffer *, GBufferLine *, size_t);
 
+/* Emballe une expression conditionelle. */
+GBufferLine *g_lang_output_encapsulate_condition(GLangOutput *, GCodeBuffer *, GBufferLine *, bool);
+
 
 
 typedef unsigned int lang_t;
-- 
cgit v0.11.2-87-g4458