From 5b89c8369d2a26089f22be7c482e8254244ebc8c Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 2 Feb 2013 18:51:02 +0000
Subject: Closed some switch cases with a 'break' keyword.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@336 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                     |  31 ++++
 plugins/androhelpers/switch.c |  46 ++++++
 src/analysis/block-int.h      |   5 +
 src/analysis/block.c          |  21 +++
 src/analysis/block.h          |   3 +
 src/analysis/blocks/flow.c    |  27 +++
 src/analysis/blocks/virtual.c |  27 +++
 src/analysis/decomp/il.c      | 373 +++++++++++++++++++++++++++++++-----------
 src/analysis/disass/macro.c   |  97 ++++++++++-
 src/arch/dalvik/decomp/if.c   |   5 +-
 src/arch/dalvik/instruction.c |  12 +-
 src/decomp/instr/Makefile.am  |   1 +
 src/decomp/instr/keyword.c    | 162 ++++++++++++++++++
 src/decomp/instr/keyword.h    |  68 ++++++++
 src/decomp/instr/switch.c     |  11 +-
 15 files changed, 768 insertions(+), 121 deletions(-)
 create mode 100644 src/decomp/instr/keyword.c
 create mode 100644 src/decomp/instr/keyword.h

diff --git a/ChangeLog b/ChangeLog
index 6c9b261..48a5414 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+13-02-02  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/androhelpers/switch.c:
+	Ensure that switch cases which share instructions have distinct blocks.
+
+	* src/analysis/block.c:
+	* src/analysis/block.h:
+	* src/analysis/block-int.h:
+	* src/analysis/blocks/flow.c:
+	* src/analysis/blocks/virtual.c:
+	Provide leaf blocks of a group of blocks.
+
+	* src/analysis/decomp/il.c:
+	Reorganize the code. Close some switch cases with a 'break' keyword.
+
+	* src/analysis/disass/macro.c:
+
+	* src/arch/dalvik/decomp/if.c:
+	* src/arch/dalvik/instruction.c:
+	Decompile more 'if' instructions.
+
+	* src/decomp/instr/keyword.c:
+	* src/decomp/instr/keyword.h:
+	New entries: allow to insert the 'break' keyword in decompiled code.
+
+	* src/decomp/instr/Makefile.am:
+	Add the 'keyword.[ch]' files to libdecompinstr_la_SOURCES.
+
+	* src/decomp/instr/switch.c:
+	Typos.
+
 13-01-31  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/androhelpers/switch.c:
diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c
index 0a1e488..3bb900f 100644
--- a/plugins/androhelpers/switch.c
+++ b/plugins/androhelpers/switch.c
@@ -42,6 +42,9 @@ static bool load_dex_switch(const GArchInstruction *, GArchInstruction *, const
 /* Lie les instructions selon les cas d'un aiguillage. */
 static void link_all_switch_cases(GArchInstruction *, const dex_switch *, GArchInstruction *, vmpa_t, vmpa_t);
 
+/* Prend en compte les absences de 'break' dans les cas. */
+static void ensure_each_case_has_its_block(GArchInstruction *, GArchInstruction *);
+
 /* Insère des indications dans le texte humainement lisibles. */
 static void mark_all_switch_cases(const GArchInstruction *, const dex_switch *, GArchInstruction *, const GLoadedBinary *, vmpa_t, vmpa_t);
 
@@ -166,6 +169,7 @@ static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dsw
 
             imm = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, value);
             g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP, imm);
+            ensure_each_case_has_its_block(next, instrs);
 
         }
 
@@ -176,7 +180,49 @@ static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dsw
     next = g_arch_instruction_get_next_iter(instrs, instr, end);
 
     if (next != NULL)
+    {
         g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP, NULL);
+        ensure_each_case_has_its_block(next, instrs);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction d'aiguillage rencontrée.               *
+*                instrs  = liste des instructions pour tout le binaire.       *
+*                                                                             *
+*  Description : Prend en compte les absences de 'break' dans les cas.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void ensure_each_case_has_its_block(GArchInstruction *instr, GArchInstruction *instrs)
+{
+    GArchInstruction *prev;                 /* Instruction avant un cas    */
+
+    /**
+     * La situation où un cas n'a pas de 'break' conduit à une fusion du corps
+     * du cas avec le corps du cas suivant (partie commune).
+     * La fin du premier cas n'ayant pas de saut enregistré, rien n'entraîne un
+     * lien logique, et donc une séparation des deux cas en blocs distincts.
+     *
+     * Cette procédure établit les vérifications nécessaires, et rétablit
+     * la logique des liens et des blocs en cas de besoin.
+     */
+
+    prev = g_arch_instruction_get_prev_iter(instrs, instr);
+
+    if (prev != NULL
+        && !g_arch_instruction_has_destinations(prev)
+        && !g_arch_instruction_is_return(prev))
+    {
+        g_arch_instruction_link_with(prev, instr, ILT_EXEC_FLOW, NULL);
+    }
 
 }
 
diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h
index 419a8b0..069b50c 100644
--- a/src/analysis/block-int.h
+++ b/src/analysis/block-int.h
@@ -38,6 +38,10 @@ typedef bool (* visit_all_blocks_fc) (GInstrBlock *, instr_block_visitor_cb, voi
 /* Etablit la liste de tous les blocs présents. */
 typedef void (* list_all_blocks_fc) (const GInstrBlock *, GInstrBlock ***, size_t *);
 
+/* Etablit la liste de tous les blocs terminaux. */
+typedef void (* list_leafs_blocks_fc) (const GInstrBlock *, GInstrBlock ***, size_t *);
+
+
 /* Fournit les différents accès aux registres. */
 //typedef const reg_access * (* list_regs_accesses_fc) (const GInstrBlock *, size_t *);
 
@@ -51,6 +55,7 @@ struct _GInstrBlock
     find_by_addr_fc find_by_addr;           /* Recherche par adresse       */
     visit_all_blocks_fc visit_blocks;       /* Visite des différents blocs */
     list_all_blocks_fc list_blocks;         /* Liste de tous les blocs     */
+    list_leafs_blocks_fc list_leafs;        /* Liste des blocs terminaux   */
     //list_regs_accesses_fc list_regs;        /* Liste des accès registres   */
 
     GInstrBlock *links_block;               /* Lieu des blocs attachés     */
diff --git a/src/analysis/block.c b/src/analysis/block.c
index 50d5644..d8d906a 100644
--- a/src/analysis/block.c
+++ b/src/analysis/block.c
@@ -202,6 +202,27 @@ void g_instr_block_list_all_blocks(const GInstrBlock *block, GInstrBlock ***list
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                list  = ensemble de blocs à compléter. [OUT]                 *
+*                count = nombre de blocs au total. [OUT]                      *
+*                                                                             *
+*  Description : Etablit la liste de tous les blocs terminaux.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_instr_block_list_leafs_blocks(const GInstrBlock *block, GInstrBlock ***list, size_t *count)
+{
+    block->list_leafs(block, list, count);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block = bloc d'instructions à mettre à jour.                 *
 *                links = bloc contenant les blocs liés au bloc.               *
 *                                                                             *
diff --git a/src/analysis/block.h b/src/analysis/block.h
index 7786ce5..d4e5a2b 100644
--- a/src/analysis/block.h
+++ b/src/analysis/block.h
@@ -74,6 +74,9 @@ bool g_instr_block_visit(GInstrBlock *, instr_block_visitor_cb, void *);
 /* Etablit la liste de tous les blocs présents. */
 void g_instr_block_list_all_blocks(const GInstrBlock *, GInstrBlock ***, size_t *);
 
+/* Etablit la liste de tous les blocs terminaux. */
+void g_instr_block_list_leafs_blocks(const GInstrBlock *, GInstrBlock ***, size_t *);
+
 /* Définit l'ensemble contenant les blocs liés. */
 void g_instr_block_set_links_block(GInstrBlock *, GInstrBlock *);
 
diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c
index 4df729c..0b68a14 100644
--- a/src/analysis/blocks/flow.c
+++ b/src/analysis/blocks/flow.c
@@ -74,6 +74,9 @@ static bool g_flow_block_visit(GFlowBlock *, instr_block_visitor_cb, void *);
 /* Etablit la liste de tous les blocs présents. */
 static void g_flow_block_list_all_blocks(const GFlowBlock *, GInstrBlock ***, size_t *);
 
+/* Etablit la liste de tous les blocs terminaux. */
+static void g_flow_block_list_leafs_blocks(const GFlowBlock *, GInstrBlock ***, size_t *);
+
 /* Prend note de l'usage d'un registre, au besoin. */
 static void g_flow_block_memorize_access(GFlowBlock *, GArchRegister *, RegAccessType, vmpa_t);
 
@@ -134,6 +137,7 @@ static void g_flow_block_init(GFlowBlock *block)
     parent->find_by_addr = (find_by_addr_fc)g_flow_block_find_by_addr;
     parent->visit_blocks = (visit_all_blocks_fc)g_flow_block_visit;
     parent->list_blocks = (list_all_blocks_fc)g_flow_block_list_all_blocks;
+    parent->list_leafs = (list_leafs_blocks_fc)g_flow_block_list_leafs_blocks;
     //parent->list_regs = (list_regs_accesses_fc)g_flow_block_list_regs_accesses;
 
     block->regs = g_raccess_list_new();
@@ -315,6 +319,29 @@ static void g_flow_block_list_all_blocks(const GFlowBlock *block, GInstrBlock **
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                list  = ensemble de blocs à compléter. [OUT]                 *
+*                count = nombre de blocs au total. [OUT]                      *
+*                                                                             *
+*  Description : Etablit la liste de tous les blocs terminaux.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_list_leafs_blocks(const GFlowBlock *block, GInstrBlock ***list, size_t *count)
+{
+    (*list) = (GInstrBlock **)realloc(*list, ++(*count) * sizeof(GInstrBlock *));
+
+    (*list)[*count - 1] = G_INSTR_BLOCK(block);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block = bloc d'instructions à mettre à jour.                 *
 *                reg   = registre visé par l'opération.                       *
 *                type  = type d'accès à l'opérande.                           *
diff --git a/src/analysis/blocks/virtual.c b/src/analysis/blocks/virtual.c
index 42492e9..0cc6a0d 100644
--- a/src/analysis/blocks/virtual.c
+++ b/src/analysis/blocks/virtual.c
@@ -79,6 +79,9 @@ static bool g_virtual_block_visit(GVirtualBlock *, instr_block_visitor_cb, void
 /* Etablit la liste de tous les blocs présents. */
 static void g_virtual_block_list_all_blocks(const GVirtualBlock *, GInstrBlock ***, size_t *);
 
+/* Etablit la liste de tous les blocs terminaux. */
+static void g_virtual_block_list_leafs_blocks(const GVirtualBlock *, GInstrBlock ***, size_t *);
+
 /* Fournit les différents accès aux registres. */
 //static const reg_access *g_virtual_block_list_regs_accesses(const GVirtualBlock *, size_t *);
 
@@ -133,6 +136,7 @@ static void g_virtual_block_init(GVirtualBlock *block)
     parent->find_by_addr = (find_by_addr_fc)g_virtual_block_find_by_addr;
     parent->visit_blocks = (visit_all_blocks_fc)g_virtual_block_visit;
     parent->list_blocks = (list_all_blocks_fc)g_virtual_block_list_all_blocks;
+    parent->list_leafs = (list_leafs_blocks_fc)g_virtual_block_list_leafs_blocks;
     //parent->list_regs = (list_regs_accesses_fc)g_virtual_block_list_regs_accesses;
 
 }
@@ -300,6 +304,29 @@ static void g_virtual_block_list_all_blocks(const GVirtualBlock *block, GInstrBl
 
 }
 
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                list  = ensemble de blocs à compléter. [OUT]                 *
+*                count = nombre de blocs au total. [OUT]                      *
+*                                                                             *
+*  Description : Etablit la liste de tous les blocs terminaux.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_virtual_block_list_leafs_blocks(const GVirtualBlock *block, GInstrBlock ***list, size_t *count)
+{
+    if (block->children_count > 0)
+        g_instr_block_list_leafs_blocks(block->children[block->children_count - 1], list, count);
+
+}
+
+
 #if 0
 /******************************************************************************
 *                                                                             *
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
index f241e46..9e235a6 100644
--- a/src/analysis/decomp/il.c
+++ b/src/analysis/decomp/il.c
@@ -24,11 +24,15 @@
 #include "il.h"
 
 
+#include <malloc.h>
+
+
 #include "../blocks/flow.h"
 #include "../blocks/virtual.h"
 #include "../../decomp/expr/block.h"
 #include "../../decomp/expr/immediate.h"
 #include "../../decomp/instr/ite.h"
+#include "../../decomp/instr/keyword.h"
 #include "../../decomp/instr/switch.h"
 
 
@@ -67,6 +71,20 @@ static GDecInstruction *decompiled_basic_block(GInstrBlock *, GDecContext *);
 
 
 
+/* --------------------------- DECOMPILATIONS SPECIFIQUES --------------------------- */
+
+
+/* Procède à la décompilation des éléments d'un 'if then else'. */
+static void build_ite_branches(GITEInstruction *, GFlowBlock *, GDecContext *);
+
+/* Termine le traitement d'un cas de 'switch'. */
+static void close_case_decomp_instructions(GDecInstruction *, GInstrBlock *, GArchInstruction **, size_t, size_t);
+
+/* Procède à la décompilation des éléments d'un 'switch'. */
+static void build_switch_branches(GSwitchInstruction *, GFlowBlock *, GDecContext *);
+
+
+
 /* ---------------------------------------------------------------------------------- */
 /*                       GESTION DES CONTEXTES DE DECOMPILATION                       */
 /* ---------------------------------------------------------------------------------- */
@@ -328,27 +346,12 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
 {
     GArchInstruction *instrs;               /* Liste d'instructions natives*/
     GArchInstruction *first;                /* Première instruction du lot */
-    GArchInstruction *last;                 /* Dernière instruction du lot */
     vmpa_t max;                             /* Adresse de fin du bloc      */
     GArchInstruction *iter;                 /* Boucle de parcours #1       */
     GDecInstruction *decomp;                /* Dernier résultat de décomp. */
-    GInstrBlock *sub_parent;                /* Groupe des sous-branches    */
-    GHashTable *sub_shared;                 /* Allocations communes        */
-    GDecContext *sub_ctx;                   /* Sous-contexte pour branche  */
-    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */
-    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */
-    GArchInstruction *next;                 /* Instruction de branchement  */
-    vmpa_t next_addr;                       /* Adresse de cette instruct°  */
-    GInstrBlock *next_block;                /* Sous-bloc basique direct    */
-    GArchInstruction **dests;               /* Instr. visée par une autre  */
-    link_extra_info *info;                  /* Compléments pour les liens  */
-    size_t dcount;                          /* Nombre de liens de dest.    */
-    size_t i;                               /* Boucle de parcours #2       */
-    GDecInstruction *case_dinstr;           /* Décompilation 'case'        */
-    GDecExpression *case_value;             /* Valeur d'aiguillage         */
 
     instrs = g_flow_block_get_all_instructions_list(block);
-    g_flow_block_get_boundary(block, &first, &last);
+    g_flow_block_get_boundary(block, &first, NULL);
 
     g_flow_block_get_boundary_addresses(block, NULL, &max);
     max++;
@@ -366,92 +369,11 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
 
     /* if ... then ... else ... */
     if (G_IS_ITE_INSTRUCTION(decomp))
-    {
-        sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
-        sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash,
-                                           (GEqualFunc)g_arch_register_equal,
-                                           g_object_unref, g_object_unref);
-
-        true_dinstr = NULL;
-
-        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE);
-        if (next != NULL)
-        {
-            g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
-            next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
-
-            if (next_block != NULL)
-            {
-                sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
-                true_dinstr = decompiled_basic_block(next_block, sub_ctx);
-                g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
-                g_object_unref(G_OBJECT(sub_ctx));
-            }
-
-        }
-
-        false_dinstr = NULL;
-
-        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE);
-        if (next != NULL)
-        {
-            g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
-            next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
-
-            if (next_block != NULL)
-            {
-                sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
-                false_dinstr = decompiled_basic_block(next_block, sub_ctx);
-                g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
-                g_object_unref(G_OBJECT(sub_ctx));
-            }
-
-        }
-
-        g_ite_instruction_set_branches(G_ITE_INSTRUCTION(decomp), true_dinstr, false_dinstr);
-
-        g_hash_table_unref(sub_shared);
-
-    }
+        build_ite_branches(G_ITE_INSTRUCTION(decomp), block, ctx);
 
     /* switch ... case ... */
     else if (G_IS_SWITCH_INSTRUCTION(decomp))
-    {
-        sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
-        sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash,
-                                           (GEqualFunc)g_arch_register_equal,
-                                           g_object_unref, g_object_unref);
-
-        dcount = g_arch_instruction_get_destinations(last, &dests, NULL, &info);
-
-        for (i = 0; i < dcount; i++)
-        {
-            g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr);
-            next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
-
-            if (next_block != NULL)
-            {
-                sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
-                case_dinstr = decompiled_basic_block(next_block, sub_ctx);
-                g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
-                g_object_unref(G_OBJECT(sub_ctx));
-
-                if (info[i].imm != NULL)
-                {
-                    case_value = G_DEC_EXPRESSION(g_imm_expression_new(info[i].imm));
-                    g_switch_instruction_add_case(G_SWITCH_INSTRUCTION(decomp),
-                                                  case_value, case_dinstr, next_addr);
-                }
-                else g_switch_instruction_set_default_case(G_SWITCH_INSTRUCTION(decomp),
-                                                           case_dinstr);
-
-            }
-
-        }
-
-        g_hash_table_unref(sub_shared);
-
-    }
+        build_switch_branches(G_SWITCH_INSTRUCTION(decomp), block, ctx);
 
     /* Renvoi des instructions mises en place */
 
@@ -578,3 +500,256 @@ GDecInstruction *decompiled_routine_instructions(GBinRoutine *routine, GExeForma
     return result;
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                             DECOMPILATIONS SPECIFIQUES                             */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : decomp = instruction 'if ... then ... else' à compléter.     *
+*                block  = ensemble des instructions d'assemblage traitées.    *
+*                ctx    = contexte de soutien à associer à l'opération.       *
+*                                                                             *
+*  Description : Procède à la décompilation des éléments d'un 'if then else'. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void build_ite_branches(GITEInstruction *decomp, GFlowBlock *block, GDecContext *ctx)
+{
+    GArchInstruction *last;                 /* Dernière instruction du lot */
+    GInstrBlock *sub_parent;                /* Groupe des sous-branches    */
+    GHashTable *sub_shared;                 /* Allocations communes        */
+    GDecContext *sub_ctx;                   /* Sous-contexte pour branche  */
+    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */
+    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */
+    GArchInstruction *next;                 /* Instruction de branchement  */
+    vmpa_t next_addr;                       /* Adresse de cette instruct°  */
+    GInstrBlock *next_block;                /* Sous-bloc basique direct    */
+
+    g_flow_block_get_boundary(block, NULL, &last);
+
+    sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
+    sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash,
+                                       (GEqualFunc)g_arch_register_equal,
+                                       g_object_unref, g_object_unref);
+
+    true_dinstr = NULL;
+    false_dinstr = NULL;
+
+    /* Branche 'true' */
+    next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE);
+    if (next != NULL)
+    {
+        g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
+        next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
+
+        if (next_block != NULL)
+        {
+            sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
+            true_dinstr = decompiled_basic_block(next_block, sub_ctx);
+            g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
+            g_object_unref(G_OBJECT(sub_ctx));
+        }
+
+    }
+
+    /* Branche 'false' */
+    next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE);
+    if (next != NULL)
+    {
+        g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
+        next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
+
+        if (next_block != NULL)
+        {
+            sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
+            false_dinstr = decompiled_basic_block(next_block, sub_ctx);
+            g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
+            g_object_unref(G_OBJECT(sub_ctx));
+        }
+
+    }
+
+    g_ite_instruction_set_branches(decomp, true_dinstr, false_dinstr);
+
+    g_hash_table_unref(sub_shared);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : case_dinstr = instructions d'un cas de 'switch' décompilées. *
+*                case_block  = bloc d'instructions assembleur correspondantes.*
+*                cases       = listes des instructions des différents cas.    *
+*                current     = indice du cas courant.                         *
+*                ccount      = nombre de cas présents dans le 'switch'.       *
+*                                                                             *
+*  Description : Termine le traitement d'un cas de 'switch'.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void close_case_decomp_instructions(GDecInstruction *case_dinstr, GInstrBlock *case_block, GArchInstruction **cases, size_t current, size_t ccount)
+{
+    vmpa_t *cases_addr;                     /* Adresses des cas du 'switch'*/
+    size_t i;                               /* Boucle de parcours #1       */
+    GInstrBlock **leafs;                    /* Blocs terminaux du cas      */
+    size_t lcount;                          /* Nombre de blocs terminaux   */
+    vmpa_t common_addr;                     /* Adresse commune de suite    */
+    bool is_common;                         /* Suite commune ?             */
+    GArchInstruction *last;                 /* Dernière instruction de bloc*/
+    GArchInstruction **dests;               /* Instr. visée par une autre  */
+    size_t dcount;                          /* Nombre de liens de dest.    */
+    size_t j;                               /* Boucle de parcours #2       */
+    vmpa_t addr;                            /* Adresse d'une instruction   */
+    bool jump_to_case;                      /* Suite dans le cas suivant ? */
+
+    /* Etablit la liste des adresses des cas */
+
+    cases_addr = (vmpa_t *)calloc(ccount, sizeof(vmpa_t));
+
+    for (i = 0; i < ccount; i++)
+        g_arch_instruction_get_location(cases[i], NULL, NULL, &cases_addr[i]);
+
+    /* Récupère la (les) fin(s) du cas présent */
+
+    leafs = NULL;
+    lcount = 0;
+
+    g_instr_block_list_leafs_blocks(case_block, &leafs, &lcount);
+
+    /* Procède à une première analyse de la suite */
+
+    common_addr = VMPA_MAX;
+    is_common = true;
+
+    for (i = 0; i < lcount && is_common; i++)
+    {
+        g_flow_block_get_boundary(G_FLOW_BLOCK(leafs[i]), NULL, &last);
+        dcount = g_arch_instruction_get_destinations(last, &dests, NULL, NULL);
+
+        for (j = 0; j < dcount && is_common; j++)
+        {
+            g_arch_instruction_get_location(dests[j], NULL, NULL, &addr);
+
+            if (common_addr == VMPA_MAX)
+                common_addr = addr;
+            else
+                is_common = (common_addr == addr);
+
+        }
+
+    }
+
+    /* La sortie du cas est unique ! */
+    if (is_common)
+    {
+        if (common_addr == VMPA_MAX)
+            goto ecdi_exit;
+
+        jump_to_case = false;
+
+        for (i = 0; i < ccount && !jump_to_case; i++)
+            if (i != current)
+                jump_to_case = (cases_addr[i] == common_addr);
+
+        if (!jump_to_case)
+            g_expr_block_add_item(G_EXPR_BLOCK(case_dinstr), g_keyword_instruction_new(DKW_BREAK));
+
+    }
+
+    /* ... ou il faut suivre les différentes branches... */
+    else
+    {
+
+        /* TODO */
+
+    }
+
+ ecdi_exit:
+
+    free(cases_addr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : decomp = instruction 'switch' à compléter.                   *
+*                block  = ensemble des instructions d'assemblage traitées.    *
+*                ctx    = contexte de soutien à associer à l'opération.       *
+*                                                                             *
+*  Description : Procède à la décompilation des éléments d'un 'switch'.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void build_switch_branches(GSwitchInstruction *decomp, GFlowBlock *block, GDecContext *ctx)
+{
+    GArchInstruction *last;                 /* Dernière instruction du lot */
+    GInstrBlock *sub_parent;                /* Groupe des sous-branches    */
+    GHashTable *sub_shared;                 /* Allocations communes        */
+    GDecContext *sub_ctx;                   /* Sous-contexte pour branche  */
+    vmpa_t next_addr;                       /* Adresse de cette instruct°  */
+    GInstrBlock *next_block;                /* Sous-bloc basique direct    */
+    GArchInstruction **dests;               /* Instr. visée par une autre  */
+    link_extra_info *info;                  /* Compléments pour les liens  */
+    size_t dcount;                          /* Nombre de liens de dest.    */
+    size_t i;                               /* Boucle de parcours #2       */
+    GDecInstruction *case_dinstr;           /* Décompilation 'case'        */
+    GDecExpression *case_value;             /* Valeur d'aiguillage         */
+
+    g_flow_block_get_boundary(block, NULL, &last);
+
+    sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
+    sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash,
+                                       (GEqualFunc)g_arch_register_equal,
+                                       g_object_unref, g_object_unref);
+
+    dcount = g_arch_instruction_get_destinations(last, &dests, NULL, &info);
+
+    for (i = 0; i < dcount; i++)
+    {
+        g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr);
+        next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
+
+        if (next_block != NULL)
+        {
+            sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
+            case_dinstr = decompiled_basic_block(next_block, sub_ctx);
+            g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
+            g_object_unref(G_OBJECT(sub_ctx));
+
+            close_case_decomp_instructions(case_dinstr, next_block, dests, i, dcount);
+
+            if (info[i].imm != NULL)
+            {
+                case_value = G_DEC_EXPRESSION(g_imm_expression_new(info[i].imm));
+                g_switch_instruction_add_case(G_SWITCH_INSTRUCTION(decomp),
+                                              case_value, case_dinstr, next_addr);
+            }
+            else g_switch_instruction_set_default_case(G_SWITCH_INSTRUCTION(decomp),
+                                                       case_dinstr);
+
+        }
+
+    }
+
+    g_hash_table_unref(sub_shared);
+
+}
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 14dad95..993f70f 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -52,7 +52,7 @@ typedef struct _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);
+static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool, size_t *);
 
 /* Identifie les différents points de passage d'une branche. */
 static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *);
@@ -73,6 +73,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t,
 *  Paramètres  : info = informations à consulter.                             *
 *                addr = adresse à rechercher.                                 *
 *                fast = autorise une recherche rapide.                        *
+*                pos  = enregistrement de la position de la trouvaille. [OUT] *
 *                                                                             *
 *  Description : Indique si une adresse est retenue comme point de passage.   *
 *                                                                             *
@@ -82,7 +83,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t,
 *                                                                             *
 ******************************************************************************/
 
-static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast)
+static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast, size_t *pos)
 {
     bool result;                            /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
@@ -92,12 +93,20 @@ static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool
 
     if (!fast)
         for (i = 0; i < info->count && !result; i++)
+        {
             result = (info->jumps[i] == *addr);
+            if (result && pos != NULL)
+                *pos = i;
+        }
 
     else
     {
         ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
         result = (ptr != NULL);
+
+        if (result && pos != NULL)
+            *pos = (ptr - ((void *)info->jumps)) / sizeof(vmpa_t);
+
     }
 
     return result;
@@ -130,7 +139,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
     vmpa_t addr;                            /* Adresse de la destination   */
 
     /* On évite de boucler... */
-    if (is_addr_in_branch(info, &start, false))
+    if (is_addr_in_branch(info, &start, false, NULL))
         return;
 
     info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
@@ -174,7 +183,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
     }
 
     /* Si on termine... */
-    if (iter != NULL && !is_addr_in_branch(info, &end, false))
+    if (iter != NULL && !is_addr_in_branch(info, &end, false, NULL))
     {
         info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
         info->jumps[info->count - 1] = end;
@@ -208,7 +217,7 @@ static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b)
     //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))
+        if (is_addr_in_branch(b, &a->jumps[i], false, NULL))
             result = a->jumps[i];
 
     return result;
@@ -247,7 +256,7 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
         keep = true;
 
         for (j = 1; j < count && keep; j++)
-            keep = is_addr_in_branch(&list[j], &list[0].jumps[i], false);
+            keep = is_addr_in_branch(&list[j], &list[0].jumps[i], false, NULL);
 
         if (keep)
             result = list[0].jumps[i];
@@ -259,6 +268,51 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
 }
 
 
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = liste d'ensembles de jalons à parcourir.             *
+*                count = taille de cette liste.                               *
+*                                                                             *
+*  Description : Retrouve le point de ralliement entre un groupe de branches. *
+*                                                                             *
+*  Retour      : Adresse commune aux branches.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static vmpa_t avoid_cases_common_part(const branch_info *list, size_t cur, size_t count, vmpa_t max)
+{
+    vmpa_t result;                          /* Adresse trouvée à retourner */
+    size_t found_pos;                       /* Plus petit tronc commun     */
+    size_t i;                               /* Boucle de parcours          */
+    size_t pos;                             /* Emplacement du cas commun   */
+
+    result = max;
+
+    found_pos = list[cur].count;
+
+    for (i = 0; i < count; i++)
+    {
+        if (i == cur) continue;
+
+        if (is_addr_in_branch(&list[cur], &list[i].jumps[0], false, &pos))
+        {
+            if (pos < found_pos)
+                result = list[i].jumps[0];
+        }
+
+    }
+
+    return result;
+
+}
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instrs = ensemble des instructions d'assemblage.             *
@@ -447,13 +501,38 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
             parent = block;
             group = g_virtual_block_new();
 
+            do
+            {
+                size_t _i, _j;
+
+                for (_i = 0; _i < cases_count; _i++)
+                {
+                    printf("  [case %d] : ", _i);
+
+                    for (_j = 0; _j < cases_branches[_i].count; _j++)
+                        printf("0x%08lx ", cases_branches[_i].jumps[_j]);
+
+                    printf("\n");
+
+                }
+
+            } while (0);
+
+
             for (j = 0; j < cases_count; j++)
             {
-                printf(" ## %zu...", j);
+                printf(" ## %zu start=0x%08lx (0x%08lx)...\n", j, cases_branches[j].jumps[0],
+                       next_addr);
+
+                //block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr);
+
+                //next_addr = avoid_cases_common_part(cases_branches, j, cases_count, next_addr);
 
-                block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr);
+                block = build_instruction_block(instrs, cases_branches[j].jumps[0], end,
+                                                avoid_cases_common_part(cases_branches, j, cases_count, next_addr));
 
-                printf(" %p\n", block);
+                printf(" %p (0x%08lx)\n", block,
+                       avoid_cases_common_part(cases_branches, j, cases_count, next_addr));
 
                 if (block != NULL)
 
diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c
index 93e21d9..f7591b9 100644
--- a/src/arch/dalvik/decomp/if.c
+++ b/src/arch/dalvik/decomp/if.c
@@ -26,6 +26,7 @@
 
 #include "../instruction.h"
 #include "../../../decomp/expr/cond.h"
+#include "../../../decomp/expr/immediate.h"
 #include "../../../decomp/instr/ite.h"
 
 
@@ -153,8 +154,8 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec
     operand = g_arch_instruction_get_operand(instr, 0);
     op1 = g_dec_context_convert_register(ctx, operand, false, addr);
 
-    operand = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, (unsigned int)0);
-    op2 = g_imm_expression_new(operand);
+    operand = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, (unsigned int)0);
+    op2 = g_imm_expression_new(G_IMM_OPERAND(operand));
 
     operand = g_arch_instruction_get_operand(instr, 2);
     jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/
diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c
index 81b8993..1ab6e3c 100644
--- a/src/arch/dalvik/instruction.c
+++ b/src/arch/dalvik/instruction.c
@@ -117,12 +117,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"/*,             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_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 */ },
diff --git a/src/decomp/instr/Makefile.am b/src/decomp/instr/Makefile.am
index 6120cac..d299cd2 100644
--- a/src/decomp/instr/Makefile.am
+++ b/src/decomp/instr/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdecompinstr.la
 
 libdecompinstr_la_SOURCES =				\
 	ite.h ite.c							\
+	keyword.h keyword.c					\
 	switch.h switch.c
 
 libdecompinstr_la_LDFLAGS = 
diff --git a/src/decomp/instr/keyword.c b/src/decomp/instr/keyword.c
new file mode 100644
index 0000000..eca1530
--- /dev/null
+++ b/src/decomp/instr/keyword.c
@@ -0,0 +1,162 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * keyword.c - insertions de mots clefs de haut niveau
+ *
+ * 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 "keyword.h"
+
+
+#include "../instruction-int.h"
+
+
+
+/* Définition d'un mot clef de haut niveau (instance) */
+struct _GKeywordInstruction
+{
+    GDecInstruction parent;                 /* A laisser en premier        */
+
+    DecompiledKeyWord keyword;              /* Mot clef représenté         */
+
+};
+
+
+/* Indique le type défini pour un mot clef de haut niveau. */
+struct _GKeywordInstructionClass
+{
+    GDecInstructionClass parent;            /* A laisser en premier        */
+
+};
+
+
+
+/* Initialise la classe des mots clefs de haut niveau. */
+static void g_keyword_instruction_class_init(GKeywordInstructionClass *);
+
+/* Initialise une instance de mot clef de haut niveau. */
+static void g_keyword_instruction_init(GKeywordInstruction *);
+
+/* Imprime pour l'écran un version humaine d'une instruction. */
+static GBufferLine *g_keyword_instruction_print(const GKeywordInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *);
+
+
+
+/* Indique le type défini pour un mot clef de haut niveau. */
+G_DEFINE_TYPE(GKeywordInstruction, g_keyword_instruction, G_TYPE_DEC_INSTRUCTION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des mots clefs de haut niveau.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_keyword_instruction_class_init(GKeywordInstructionClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une instance de mot clef de haut niveau.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_keyword_instruction_init(GKeywordInstruction *instr)
+{
+    GDecInstruction *base;                  /* Autre version de l'objet    */
+
+    base = G_DEC_INSTRUCTION(instr);
+
+    base->print = (dec_instr_print_fc)g_keyword_instruction_print;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : keyword = mot clef à représenter.                            *
+*                                                                             *
+*  Description : Crée un mot clef de haut niveau.                             *
+*                                                                             *
+*  Retour      : Instruction mise en place.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *g_keyword_instruction_new(DecompiledKeyWord keyword)
+{
+    GKeywordInstruction *result;              /* Expression à retourner      */
+
+    result = g_object_new(G_TYPE_KEYWORD_INSTRUCTION, NULL);
+
+    result->keyword = keyword;
+
+    return G_DEC_INSTRUCTION(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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.          *
+*                output = langage de programmation de sortie.                 *
+*                                                                             *
+*  Description : Imprime pour l'écran un version humaine d'une instruction.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBufferLine *g_keyword_instruction_print(const GKeywordInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
+{
+    switch (instr->keyword)
+    {
+        case DKW_BREAK:
+            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "break", 5, RTT_KEY_WORD);
+            break;
+
+        case DKW_CONTINUE:
+            g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "continue", 8, RTT_KEY_WORD);
+            break;
+
+    }
+
+    return line;
+
+}
diff --git a/src/decomp/instr/keyword.h b/src/decomp/instr/keyword.h
new file mode 100644
index 0000000..69d6901
--- /dev/null
+++ b/src/decomp/instr/keyword.h
@@ -0,0 +1,68 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * keyword.h - prototypes pour les insertions de mots clefs de haut niveau
+ *
+ * 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_INSTR_KEYWORD_H
+#define _DECOMP_INSTR_KEYWORD_H
+
+
+#include <glib-object.h>
+
+
+#include "../instruction.h"
+
+
+
+#define G_TYPE_KEYWORD_INSTRUCTION               g_keyword_instruction_get_type()
+#define G_KEYWORD_INSTRUCTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_keyword_instruction_get_type(), GKeywordInstruction))
+#define G_IS_KEYWORD_INSTRUCTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_keyword_instruction_get_type()))
+#define G_KEYWORD_INSTRUCTION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KEYWORD_INSTRUCTION, GKeywordInstructionClass))
+#define G_IS_KEYWORD_INSTRUCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KEYWORD_INSTRUCTION))
+#define G_KEYWORD_INSTRUCTION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KEYWORD_INSTRUCTION, GKeywordInstructionClass))
+
+
+
+/* Type de mots clefs pris en charge */
+typedef enum _DecompiledKeyWord
+{
+    DKW_BREAK,                              /* 'break'                     */
+    DKW_CONTINUE,                           /* 'continue'                  */
+
+} DecompiledKeyWord;
+
+
+/* Définition d'un mot clef de haut niveau (instance) */
+typedef struct _GKeywordInstruction GKeywordInstruction;
+
+/* Définition d'un mot clef de haut niveau (classe) */
+typedef struct _GKeywordInstructionClass GKeywordInstructionClass;
+
+
+/* Indique le type défini pour un mot clef de haut niveau. */
+GType g_keyword_instruction_get_type(void);
+
+/* Crée un mot clef de haut niveau. */
+GDecInstruction *g_keyword_instruction_new(DecompiledKeyWord);
+
+
+
+#endif  /* _DECOMP_INSTR_KEYWORD_H */
diff --git a/src/decomp/instr/switch.c b/src/decomp/instr/switch.c
index 3c204a0..4b1662b 100644
--- a/src/decomp/instr/switch.c
+++ b/src/decomp/instr/switch.c
@@ -31,15 +31,16 @@
 #include "../instruction-int.h"
 
 
+
 /* Détails d'un cas */
 typedef struct _case_info
 {
-    vmpa_t addr;                            /* Adresse des blocs associés */
+    vmpa_t addr;                            /* Adresse des blocs associés  */
 
-    GDecExpression **values;                /* Valeur d'embranchement     */
-    size_t values_count;                    /* Quantité de cas rassemblés */
+    GDecExpression **values;                /* Valeur d'embranchement      */
+    size_t values_count;                    /* Quantité de cas rassemblés  */
 
-    GDecInstruction *instrs;                /* Instructions du cas        */
+    GDecInstruction *instrs;                /* Instructions du cas         */
 
 } case_info;
 
@@ -138,7 +139,7 @@ static void g_switch_instruction_init(GSwitchInstruction *instr)
 *                                                                             *
 *  Description : Exprime un aiguillage multiple du flux selon une valeur.     *
 *                                                                             *
-*  Retour      : Expression mise en place.                                    *
+*  Retour      : Instruction mise en place.                                   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
-- 
cgit v0.11.2-87-g4458