From 141d2f0fbb2ce3b4ddf85383c55b891fd59dc598 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 24 Jan 2015 11:19:32 +0000
Subject: Introduced conditional calls in instruction definition rules.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@459 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           |   82 +++
 src/analysis/disass/area.c          |  116 +++-
 src/analysis/disass/fetch.c         |   17 +
 src/arch/arm/v456/instruction.c     |    2 +-
 src/arch/arm/v7/context.c           |   48 +-
 src/arch/arm/v7/context.h           |   15 +
 src/arch/arm/v7/link.c              |  242 ++++++-
 src/arch/arm/v7/link.h              |   33 +
 src/arch/arm/v7/opdefs/Makefile.am  |    1 +
 src/arch/arm/v7/opdefs/b_A8818.d    |   45 ++
 src/arch/arm/v7/opdefs/bl_A8825.d   |   32 +-
 src/arch/arm/v7/opdefs/blx_A8826.d  |    2 +
 src/arch/arm/v7/opdefs/bx_A8827.d   |   12 +
 src/arch/arm/v7/opdefs/cbnz_A8829.d |   14 +
 src/arch/arm/v7/opdefs/ldr_A8862.d  |    3 +
 src/arch/arm/v7/opdefs/ldr_A8863.d  |    2 +
 src/arch/arm/v7/opdefs/ldr_A8864.d  |   32 +-
 src/arch/arm/v7/opdefs/ldr_A8865.d  |    1 +
 src/arch/arm/v7/opdefs/ldrb_A8867.d |    3 +
 src/arch/arm/v7/post.c              |  189 ++++++
 src/arch/arm/v7/post.h              |    9 +
 src/arch/arm/v7/processor.c         |    7 +-
 src/arch/artificial.c               |   23 -
 src/arch/dalvik/instruction.c       |    2 +-
 src/arch/instruction-int.h          |    9 +-
 src/arch/instruction.c              |   26 +-
 src/arch/instruction.h              |    3 +
 src/arch/x86/instruction.c          |    2 +-
 tools/d2c/Makefile.am               |    2 +
 tools/d2c/args.c                    | 1161 ++++++++++++++++++++++++++++++++
 tools/d2c/args.h                    |  131 ++++
 tools/d2c/conv.c                    | 1251 ++---------------------------------
 tools/d2c/conv.h                    |   98 +--
 tools/d2c/d2c_gram.y                |   69 +-
 tools/d2c/d2c_tok.l                 |   51 +-
 tools/d2c/qckcall.c                 |  110 +++
 tools/d2c/qckcall.h                 |   44 ++
 tools/d2c/rules.c                   |   96 ++-
 tools/d2c/rules.h                   |   32 +-
 tools/d2c/spec.c                    |   13 +-
 40 files changed, 2619 insertions(+), 1411 deletions(-)
 create mode 100644 tools/d2c/args.c
 create mode 100644 tools/d2c/args.h
 create mode 100644 tools/d2c/qckcall.c
 create mode 100644 tools/d2c/qckcall.h

diff --git a/ChangeLog b/ChangeLog
index f730ae1..68a0145 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,85 @@
+15-01-24  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	Try to better follow the execution flow.
+
+	* src/analysis/disass/fetch.c:
+	Add some extra entry points. They are fixed, so this needs to be improved.
+
+	* src/arch/arm/v456/instruction.c:
+	Disable some old code.
+
+	* src/arch/arm/v7/context.c:
+	* src/arch/arm/v7/context.h:
+	Provide a way to create new drop points and memorize their encodings.
+
+	* src/arch/arm/v7/link.c:
+	* src/arch/arm/v7/link.h:
+	Handle more instructions: b, cb[n]z and ldr.
+
+	* src/arch/arm/v7/opdefs/b_A8818.d:
+	* src/arch/arm/v7/opdefs/bl_A8825.d:
+	* src/arch/arm/v7/opdefs/blx_A8826.d:
+	* src/arch/arm/v7/opdefs/bx_A8827.d:
+	* src/arch/arm/v7/opdefs/cbnz_A8829.d:
+	* src/arch/arm/v7/opdefs/ldr_A8862.d:
+	* src/arch/arm/v7/opdefs/ldr_A8863.d:
+	* src/arch/arm/v7/opdefs/ldr_A8864.d:
+	* src/arch/arm/v7/opdefs/ldr_A8865.d:
+	* src/arch/arm/v7/opdefs/ldrb_A8867.d:
+	Update hooks and rules.
+
+	* src/arch/arm/v7/opdefs/Makefile.am:
+	Register the 'DefineAsReturn' macro in D2C_MACROS.
+
+	* src/arch/arm/v7/post.c:
+	* src/arch/arm/v7/post.h:
+	Handle more instructions: b, cb[n]z and ldr.
+
+	* src/arch/arm/v7/processor.c:
+	Do not create a dummy instruction when decoding failed anymore.
+
+	* src/arch/artificial.c:
+	Remove the old 'g_db_instruction_is_return()' function.
+
+	* src/arch/dalvik/instruction.c:
+	Disable some old code.
+
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	* src/arch/instruction-int.h:
+	Change the way an instruction gives information about its 'return'-like
+	behavior property.
+
+	* src/arch/x86/instruction.c:
+	Disable some old code.
+
+	* tools/d2c/args.c:
+	* tools/d2c/args.h:
+	New entries: handle expressions used as call arguments.
+
+	* tools/d2c/conv.c:
+	* tools/d2c/conv.h:
+	Update code by using new arguments.
+
+	* tools/d2c/d2c_gram.y:
+	* tools/d2c/d2c_tok.l:
+	Introduce conditional calls in instruction definition rules.
+
+	* tools/d2c/Makefile.am:
+	Add the new 'args.[ch]' and 'qckcall.[ch]' files into d2c_SOURCES.
+
+	* tools/d2c/qckcall.c:
+	* tools/d2c/qckcall.h:
+	New entries: provide a way to call functions and manage associated casts.
+
+	* tools/d2c/rules.c:
+	* tools/d2c/rules.h:
+	Introduce conditional calls in instruction definition rules.
+
+	* tools/d2c/spec.c:
+	Update code.
+
 15-01-18  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/arm/v7/opdefs/Makefile.am:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 8c46eb0..7e3a9a8 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -28,8 +28,6 @@
 
 
 
-
-
 /* Zone mémoire bien bornée */
 typedef struct _mem_area
 {
@@ -49,10 +47,6 @@ typedef struct _mem_area
 } mem_area;
 
 
-
-
-
-
 /* Initialise une aire de données à partir d'une adresse donnée. */
 static void init_mem_area_from_addr(mem_area *, const vmpa2t *, phys_t);
 
@@ -381,6 +375,14 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, const
 
     //printf(" [%p] CODE start @ %u (len=%u)\n", area, (unsigned int)diff, (unsigned int)alen);
 
+
+
+    printf(" START @ 0x%08x\n", (unsigned int)get_virt_addr(&pos));
+
+
+    bin_length = (get_phy_addr(get_mrange_addr(&area->range)) + alen);
+
+
     for (i = diff; i < alen; i += diff)
     {
         //il y a eu un point d'entrée... -> STOP
@@ -418,6 +420,26 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, const
 
         assert(!is_range_blank_in_mem_areas(list, count, &range));
 
+
+
+
+        printf(" --disass-- '%s' @ 0x%08x (break=%d)\n",
+               g_arch_instruction_get_keyword(instr, 0),
+               (unsigned int)get_virt_addr(&prev),
+               g_arch_instruction_is_return(instr));
+
+
+
+
+        if (g_arch_instruction_is_return(instr))
+            printf("BREAK @ 0x%08x\n", (unsigned int)get_virt_addr(&prev));
+
+        //continue;
+
+        /* Rupture du flot d'exécution ? */
+        if (g_arch_instruction_is_return(instr))
+            break;
+
     }
 
 
@@ -485,8 +507,9 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count
     advance_vmpa(&pos, diff);
 
     /*
-    printf(" [%p] DATA start @ 0x%08x -> %u (len=%u)\n",
-           area, (unsigned int)get_phy_addr(&pos), (unsigned int)diff, (unsigned int)alen);
+    printf(" [%p] DATA start @ 0x%08x -> %u (len=%u) => 0x%08x <-> 0x%08x\n",
+           area, (unsigned int)get_phy_addr(&pos), (unsigned int)diff, (unsigned int)alen,
+           (unsigned int)get_virt_addr(&pos), (unsigned int)(get_virt_addr(&pos) + alen));
     */
 
     for (i = diff; i < alen; i += diff)
@@ -496,7 +519,7 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count
         copy_vmpa(&prev, &pos);
 
         instr = NULL;
-
+        /*
         if (instr == NULL && (i + 4) <= alen)
         {
             init_mrange(&range, &pos, 4);
@@ -505,7 +528,7 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count
                 instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, bin_length, endianness);
 
         }
-
+        */
         if (instr == NULL && (i + 2) <= alen)
         {
             copy_vmpa(&pos, &prev);
@@ -525,10 +548,29 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count
                 instr = g_raw_instruction_new_array(bin_data, MDS_8_BITS, 1, &pos, bin_length, endianness);
             else
             {
-                printf("      break !!  0x%08x\n",
-                       (unsigned int)get_phy_addr(&pos));
-                assert(0);
-                break;
+                /**
+                 * On rencontre ici un morceau déjà traité.
+                 * On recherche donc la fin de cette partie à sauter, si elle existe.
+                 */
+
+                //////////////
+                return;
+
+
+
+                for (i++; i < alen; i++)
+                {
+                    advance_vmpa(&pos, 1);
+                    init_mrange(&range, &pos, 1);
+
+                    if (is_range_blank_in_mem_areas(list, count, &range))
+                        break;
+
+                }
+
+                diff = 0;
+                continue; 
+
             }
 
         }
@@ -551,6 +593,12 @@ static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count
 
         assert(!is_range_blank_in_mem_areas(list, count, &range));
 
+
+
+        if (area->exec) break;
+
+
+
     }
 
 }
@@ -579,11 +627,14 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GL
     phys_t i;                               /* Boucle de parcours          */
     vmpa2t start;                           /* Adresse de départ de combles*/
 
-    /*
-    printf(" === FILLING | 0x%08x (%u)...\n",
+    bool on = true;
+
+
+    printf(" === FILLING | 0x%08x // 0x%08x <-> 0x%08x...\n",
            (unsigned int)get_phy_addr(get_mrange_addr(&area->range)),
-           (unsigned int)get_phy_addr(get_mrange_addr(&area->range)));
-    */
+           (unsigned int)get_virt_addr(get_mrange_addr(&area->range)),
+           (unsigned int)(get_virt_addr(get_mrange_addr(&area->range)) + get_mrange_length(&area->range)));
+
 
     /* Les symboles se doivent d'être indépendants ! */
     if (area->has_sym) return;
@@ -597,14 +648,29 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GL
             copy_vmpa(&start, get_mrange_addr(&area->range));
             advance_vmpa(&start, i);
 
-            if (area->exec)
+            if (area->exec && get_virt_addr(&start) % 4 == 0)
+            {
                 load_code_from_mem_area(area, list, count, binary, ctx, &start, info);
 
+                if (!is_range_blank_in_mem_area(area, i, 1, NULL))
+                {
+                    printf(" --filled-- @ 0x%08x\n", (unsigned int)get_virt_addr(&start));
+                    on = false;
+                }
+                else
+                    printf(" --fill failed-- @ 0x%08x\n", (unsigned int)get_virt_addr(&start));
+
+
+            }
+
             if (is_range_blank_in_mem_area(area, i, 1, NULL))
                 load_data_from_mem_area(area, list, count, binary, ctx, &start, info);
 
         }
 
+
+        else on = true;
+
         if (is_range_blank_in_mem_area(area, i, 1, NULL))
             printf(" [%p] error with %u\n", area, (unsigned int)i);
 
@@ -1134,6 +1200,18 @@ static bool handle_bytes_map_in_mem_area(mem_area *list, size_t count, const mra
 
     else
     {
+
+        printf("BUG_ON | off=%u remaining=%u length=%u\n",
+               (unsigned int)offset,
+               (unsigned int)remaining,
+               (unsigned int)get_mrange_length(&area->range));
+
+        printf("BUG_ON @ 0x%08x + %d\n",
+               (unsigned int)get_virt_addr(get_mrange_addr(range)),
+               (int)get_mrange_length(range)
+               );
+
+
         assert(0);
 
         /* Traitement de la fin de la première aire */
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 2e9eb81..ffc653a 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -58,6 +58,8 @@ static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx
     vmpa2t addr;                            /* Conversion en pleine adresse*/
     mem_area *area;                         /* Zone de désassemblage       */
 
+    printf("-- follow 0x%08x\n", (unsigned int)virt);
+
     g_proc_context_push_drop_point(ctx, virt);
 
     while (g_proc_context_has_drop_points(ctx))
@@ -65,10 +67,20 @@ static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx
         virt = g_proc_context_pop_drop_point(ctx);
         init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
 
+
+
+        printf("  ++ point 0x%08x\n", (unsigned int)virt);
+
+
         area = find_memory_area_by_addr(areas, count, &addr);
 
         load_code_from_mem_area(area, areas, count, binary, ctx, &addr, info);
 
+
+
+        printf("  ++\n");
+
+
     }
 
 }
@@ -128,6 +140,9 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExt
 
     virt = g_binary_format_get_entry_point(format);
 
+    follow_execution_flow(binary, ctx, areas, count, info, 0x84c5);
+    follow_execution_flow(binary, ctx, areas, count, info, 0x8a65);
+
     follow_execution_flow(binary, ctx, areas, count, info, virt);
 
     /* Symboles exécutables présents et passés à travers les mailles */
@@ -147,6 +162,8 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExt
 
     }
 
+    printf(" ------------------------------------------- follow done\n");
+
     done = get_current_progessive_status(info);
 
     fini_progessive_status(info);
diff --git a/src/arch/arm/v456/instruction.c b/src/arch/arm/v456/instruction.c
index b5df0f8..4fc78a2 100644
--- a/src/arch/arm/v456/instruction.c
+++ b/src/arch/arm/v456/instruction.c
@@ -399,7 +399,7 @@ static void g_dalvik_instruction_init(GDalvikInstruction *instr)
     parent->get_rw_regs = (get_instruction_rw_regs_fc)g_dalvik_instruction_get_rw_registers;
     parent->get_text = (get_instruction_text_fc)dalvik_get_instruction_text;
     parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link;
-    parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return;
+    //parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return;
     parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile;
 
 }
diff --git a/src/arch/arm/v7/context.c b/src/arch/arm/v7/context.c
index 41ffd29..c29794d 100644
--- a/src/arch/arm/v7/context.c
+++ b/src/arch/arm/v7/context.c
@@ -24,6 +24,9 @@
 #include "context.h"
 
 
+#include <assert.h>
+
+
 #include "../context-int.h"
 
 
@@ -208,7 +211,7 @@ static void g_armv7_context_push_drop_point(GArmV7Context *ctx, virt_t addr)
 {
 
 
-	printf("PUSH v7 !!\n");
+	printf("PUSH v7 !! 0x%08x\n", addr);
 
 
 
@@ -224,6 +227,47 @@ static void g_armv7_context_push_drop_point(GArmV7Context *ctx, virt_t addr)
 
 }
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx  = contexte de désassemblage à compléter.                *
+*                addr = adresse d'un nouveau point de départ à traiter.       *
+*                                                                             *
+*  Description : Ajoute une adresse virtuelle comme point de départ de code.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_armv7_context_push_drop_point_ext(GArmV7Context *ctx, virt_t addr, ArmV7InstrSet marker)
+{
+
+
+	printf("PUSH v7 !! 0x%08x\n", (unsigned int)addr);
+
+
+
+	if (addr & 0x1)
+	{
+		addr -= 0x1;
+        assert(marker == AV7IS_THUMB);
+    }
+
+
+    g_armv7_context_define_encoding(ctx, addr, marker);
+
+	G_PROC_CONTEXT_CLASS(g_armv7_context_parent_class)->push_point(G_PROC_CONTEXT(ctx), addr);
+
+}
+
+
+
+
+
+
+
+
 
 
 /******************************************************************************
@@ -242,6 +286,8 @@ static void g_armv7_context_push_drop_point(GArmV7Context *ctx, virt_t addr)
 
 void g_armv7_context_define_encoding(GArmV7Context *ctx, virt_t addr, ArmV7InstrSet marker)
 {
+    printf(" --encoding-- @ 0x%08llx -> %d\n", (unsigned long long)addr, (int)marker);
+
     _g_arm_context_define_encoding(G_ARM_CONTEXT(ctx), addr, marker);
 
 }
diff --git a/src/arch/arm/v7/context.h b/src/arch/arm/v7/context.h
index 65b5302..a4d99d6 100644
--- a/src/arch/arm/v7/context.h
+++ b/src/arch/arm/v7/context.h
@@ -79,4 +79,19 @@ ArmV7InstrSet g_armv7_context_find_encoding(GArmV7Context *, virt_t);
 
 
 
+
+
+
+
+
+
+
+
+void g_armv7_context_push_drop_point_ext(GArmV7Context *ctx, virt_t addr, ArmV7InstrSet marker);
+
+
+
+
+
+
 #endif  /* _ARCH_ARM_V7_CONTEXT_H */
diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c
index fff0944..c1f83ac 100644
--- a/src/arch/arm/v7/link.c
+++ b/src/arch/arm/v7/link.c
@@ -25,6 +25,7 @@
 
 
 #include <assert.h>
+#include <operands/offset.h>
 
 
 
@@ -43,6 +44,54 @@
 *                                                                             *
 ******************************************************************************/
 
+void handle_links_with_instruction_b_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset)
+{
+    const mrange_t *range;                  /* Emplacementt d'instruction  */
+    virt_t pc;                              /* Position dans l'exécution   */
+    GArchOperand *op;                       /* Opérande numérique en place */
+    int32_t offset;                         /* Décallage encodé en dur     */
+    virt_t target;                          /* Adresse virtuelle visée     */
+
+    range = g_arch_instruction_get_range(instr);
+
+    pc = get_virt_addr(get_mrange_addr(range));
+
+    pc += get_mrange_length(range);
+
+    op = g_arch_instruction_get_operand(instr, 0);
+
+    if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
+        g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
+
+    else assert(0);
+
+    printf("1... 0x%x (0x%x) + 0x%x\n",
+           (unsigned int)get_virt_addr(get_mrange_addr(range)),
+           (unsigned int)pc, (unsigned int)offset);
+
+    target = pc + offset;
+
+    //g_armv7_context_define_encoding(context, target, iset);
+    g_armv7_context_push_drop_point_ext(context, target, iset);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = acès aux données du binaire d'origine.             *
+*                iset    = type de jeu d'instructions courant à faire suivre. *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
 void handle_links_with_instruction_bl_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset)
 {
     const mrange_t *range;                  /* Emplacementt d'instruction  */
@@ -69,9 +118,18 @@ void handle_links_with_instruction_bl_with_orig(GArchInstruction *instr, GArmV7C
     if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
         g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
 
+    else assert(0);
+
+    printf("2... 0x%x (0x%x) + 0x%x\n",
+           (unsigned int)get_virt_addr(get_mrange_addr(range)),
+           (unsigned int)pc, (unsigned int)offset);
+
+
+
     target = pc + offset;
 
-    g_armv7_context_define_encoding(context, target, iset);
+    //g_armv7_context_define_encoding(context, target, iset);
+    g_armv7_context_push_drop_point_ext(context, target, iset);
 
 }
 
@@ -118,8 +176,188 @@ void handle_links_with_instruction_blx_with_dest(GArchInstruction *instr, GArmV7
     if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
         g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
 
+    else assert(0);
+
+    printf("3... 0x%x (0x%x) + 0x%x\n",
+           (unsigned int)get_virt_addr(get_mrange_addr(range)),
+           (unsigned int)pc, (unsigned int)offset);
+
+
+
     target = pc + offset;
 
-    g_armv7_context_define_encoding(context, target, iset);
+    //g_armv7_context_define_encoding(context, target, iset);
+    g_armv7_context_push_drop_point_ext(context, target, iset);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = acès aux données du binaire d'origine.             *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void handle_links_with_instruction_cb_n_z(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format)
+{
+    const mrange_t *range;                  /* Emplacementt d'instruction  */
+    virt_t pc;                              /* Position dans l'exécution   */
+    GArchOperand *op;                       /* Opérande numérique en place */
+    uint32_t offset;                        /* Décallage encodé en dur     */
+    virt_t target;                          /* Adresse virtuelle visée     */
+
+    range = g_arch_instruction_get_range(instr);
+
+    pc = get_virt_addr(get_mrange_addr(range));
+
+
+    printf("PC :: 0x%08x\n", (unsigned int)pc);
+
+
+    /**
+     * En mode Thumb, pc a pour valeur l'adresse courante plus 4.
+     */
+
+    pc += 4;
+
+    op = g_arch_instruction_get_operand(instr, 1);
+
+    if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset))
+        g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
+
+    else assert(0);
+
+    target = pc + offset;
+
+    //g_armv7_context_define_encoding(context, target, AV7IS_THUMB);
+    g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = acès aux données du binaire d'origine.             *
+*                iset    = type de jeu d'instructions courant à inverser.     *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset)
+{
+    const mrange_t *range;                  /* Emplacementt d'instruction  */
+    phys_t phys_pc;                         /* Position dans l'exécution   */
+    GArchOperand *op;                       /* Opérande de surcouche       */
+    GArchOperand *sub_op;                   /* Opérande numérique en place */
+
+
+    uint32_t offset;                        /* Décallage encodé en dur     */
+    bool ret;                               /* Bilan d'une récupération    */
+
+
+    off_t val_offset;                       /* Position de valeur à lire   */
+
+
+
+    off_t length;                           /* Taille des données à lire   */
+    const bin_t *data;                      /* Données binaires à lire     */
+
+
+    uint32_t target;                        /* Adresse virtuelle visée     */
+    GArchOperand *new;                      /* Instruction de ciblage      */
+
+    /* Récupération de l'adresse visée par le chargement */
+
+    range = g_arch_instruction_get_range(instr);
+
+    phys_pc = get_phy_addr(get_mrange_addr(range));
+
+    phys_pc &= ~3;
+    //phys_pc = (phys_pc + 3) & ~3;
+
+    printf(">>>>>>> @pc @ 0x%08x\n", (unsigned int)phys_pc);
+
+
+    switch (iset)
+    {
+        case AV7IS_ARM:
+            phys_pc += 8;
+            break;
+        case AV7IS_THUMB:
+            phys_pc += 4;
+            break;
+        default:
+            assert(0);
+            break;
+    }
+
+    op = g_arch_instruction_get_operand(instr, 1);
+    assert(G_IS_ARMV7_OFFSET_OPERAND(op));
+
+    sub_op = g_armv7_offset_operand_get_value(G_ARMV7_OFFSET_OPERAND(op));
+
+    ret = g_imm_operand_get_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, &offset);
+    if (!ret)
+    {
+        assert(0);
+        return;
+    }
+
+    /* Lecture de la valeur vers laquelle renvoyer */
+
+    if (g_armv7_offset_operand_is_positive(G_ARMV7_OFFSET_OPERAND(op)))
+        val_offset = phys_pc + offset;
+    else
+        val_offset = phys_pc - offset;
+
+
+    data = g_binary_format_get_content(format, &length);
+
+
+    printf(">>>>>>> @reading @ 0x%08x (0x%x)\n", (unsigned int)val_offset, offset);
+
+
+    ret = read_u32(&target, data, &val_offset, length, SRE_LITTLE /* FIXME */);
+    if (!ret) return;
+
+
+    printf(">>>>>>> @got target :: 0x%08x\n", (unsigned int)target);
+
+
+    //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target);
+
+
+    new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target);
+    g_arch_instruction_replace_operand(instr, new, op);
+
+
+
+
+    //exit(0);
+
+
+
+    //target = pc + offset;
+
+    //g_armv7_context_define_encoding(context, target, AV7IS_THUMB);
+    g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB);
+
+
+    //exit(0);
 
 }
diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h
index ef71bd6..87bef54 100644
--- a/src/arch/arm/v7/link.h
+++ b/src/arch/arm/v7/link.h
@@ -32,6 +32,21 @@
 
 
 /* Complète un désassemblage accompli pour une instruction. */
+void handle_links_with_instruction_b_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet);
+
+
+static inline void handle_links_with_instruction_b_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
+{
+    handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB);
+}
+
+static inline void handle_links_with_instruction_b_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
+{
+    handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM);
+}
+
+
+/* Complète un désassemblage accompli pour une instruction. */
 void handle_links_with_instruction_bl_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet);
 
 
@@ -61,5 +76,23 @@ static inline void handle_links_with_instruction_blx_from_thumb(GArchInstruction
 }
 
 
+/* Complète un désassemblage accompli pour une instruction. */
+void handle_links_with_instruction_cb_n_z(GArchInstruction *, GArmV7Context *, GBinFormat *);
+
+/* Complète un désassemblage accompli pour une instruction. */
+void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet);
+
+
+static inline void handle_links_with_instruction_ldr_literal_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
+{
+    handle_links_with_instruction_ldr_literal_with_orig(ins, ctx, fmt, AV7IS_ARM);
+}
+
+static inline void handle_links_with_instruction_ldr_literal_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
+{
+    handle_links_with_instruction_ldr_literal_with_orig(ins, ctx, fmt, AV7IS_THUMB);
+}
+
+
 
 #endif  /* _ARCH_ARM_V7_LINK_H */
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index 0966e2e..fa42230 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -16,6 +16,7 @@ D2C_ENCODINGS =							\
 	-e T=thumb_32_
 
 D2C_MACROS =											\
+    -M DefineAsReturn=g_arch_instruction_define_as_return		\
     -M SetFlags=g_armv7_instruction_define_setflags		\
     -M Condition=g_arm_instruction_set_cond				\
     -M Register=translate_armv7_register				\
diff --git a/src/arch/arm/v7/opdefs/b_A8818.d b/src/arch/arm/v7/opdefs/b_A8818.d
index 50600d4..5d696a3 100644
--- a/src/arch/arm/v7/opdefs/b_A8818.d
+++ b/src/arch/arm/v7/opdefs/b_A8818.d
@@ -36,10 +36,18 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_b_from_thumb
+        post = post_process_branch_instructions
+
+    }
+
     @rules {
 
         //if cond == '1110' then UNDEFINED;
         //if cond == '1111' then SEE SVC;
+        call DefineAsReturn(1)
 
     }
 
@@ -57,9 +65,17 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_b_from_thumb
+        post = post_process_branch_instructions
+
+    }
+
     @rules {
 
         //if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        call DefineAsReturn(1)
 
     }
 
@@ -78,10 +94,18 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_b_from_thumb
+        post = post_process_branch_instructions
+
+    }
+
     @rules {
 
         //if cond<3:1> == '111' then SEE "Related encodings";
         //if InITBlock() then UNPREDICTABLE;
+        call DefineAsReturn(1)
 
     }
 
@@ -101,9 +125,17 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_b_from_thumb
+        post = post_process_branch_instructions
+
+    }
+
     @rules {
 
         //if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        call DefineAsReturn(1)
 
     }
 
@@ -122,4 +154,17 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_b_from_arm
+        post = post_process_branch_instructions
+
+    }
+
+    @rules {
+
+        call DefineAsReturn(1)
+
+    }
+
 }
diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d
index 96c782f..c5de31e 100644
--- a/src/arch/arm/v7/opdefs/bl_A8825.d
+++ b/src/arch/arm/v7/opdefs/bl_A8825.d
@@ -40,7 +40,13 @@
     @hooks {
 
         link = handle_links_with_instruction_bl_from_thumb
-        post = post_process_branch_instructions
+        post = post_process_branch_and_link_instructions
+
+    }
+
+    @rules {
+
+        //call DefineAsReturn(1)
 
     }
 
@@ -63,7 +69,13 @@
     @hooks {
 
         link = handle_links_with_instruction_blx_from_thumb
-        post = post_process_branch_instructions
+        post = post_process_branch_and_link_instructions
+
+    }
+
+    @rules {
+
+        //call DefineAsReturn(1)
 
     }
 
@@ -84,7 +96,13 @@
     @hooks {
 
         link = handle_links_with_instruction_bl_from_arm
-        post = post_process_branch_instructions
+        post = post_process_branch_and_link_instructions
+
+    }
+
+    @rules {
+
+        //call DefineAsReturn(1)
 
     }
 
@@ -105,7 +123,13 @@
     @hooks {
 
         link = handle_links_with_instruction_blx_from_arm
-        post = post_process_branch_instructions
+        post = post_process_branch_and_link_instructions
+
+    }
+
+    @rules {
+
+        //call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/blx_A8826.d b/src/arch/arm/v7/opdefs/blx_A8826.d
index 178515a..12c55ad 100644
--- a/src/arch/arm/v7/opdefs/blx_A8826.d
+++ b/src/arch/arm/v7/opdefs/blx_A8826.d
@@ -39,6 +39,7 @@
 
         //if m == 15 then UNPREDICTABLE;
         //if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        //call DefineAsReturn(1)
 
     }
 
@@ -60,6 +61,7 @@
     @rules {
 
         //if m == 15 then UNPREDICTABLE;
+        //call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d
index 45ccfd5..b8ab6f8 100644
--- a/src/arch/arm/v7/opdefs/bx_A8827.d
+++ b/src/arch/arm/v7/opdefs/bx_A8827.d
@@ -36,6 +36,12 @@
 
     }
 
+    @rules {
+
+        call DefineAsReturn(1)
+
+    }
+
 }
 
 @encoding(A1) {
@@ -51,4 +57,10 @@
 
     }
 
+    @rules {
+
+        call DefineAsReturn(1)
+
+    }
+
 }
diff --git a/src/arch/arm/v7/opdefs/cbnz_A8829.d b/src/arch/arm/v7/opdefs/cbnz_A8829.d
index 9ecf141..93a8d1f 100644
--- a/src/arch/arm/v7/opdefs/cbnz_A8829.d
+++ b/src/arch/arm/v7/opdefs/cbnz_A8829.d
@@ -36,6 +36,13 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_cb_n_z
+        post = post_process_comp_and_branch_instructions
+
+    }
+
 }
 
 @encoding(t12) {
@@ -51,4 +58,11 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_cb_n_z
+        post = post_process_comp_and_branch_instructions
+
+    }
+
 }
diff --git a/src/arch/arm/v7/opdefs/ldr_A8862.d b/src/arch/arm/v7/opdefs/ldr_A8862.d
index 7799fce..ecb530b 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8862.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8862.d
@@ -76,6 +76,7 @@
 
         //if Rn == '1111' then SEE LDR (literal);
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
@@ -103,6 +104,7 @@
         //if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
         //if P == '0' && W == '0' then UNDEFINED;
         //if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
@@ -131,6 +133,7 @@
         //if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
         //if P == '0' && W == '0' then UNDEFINED;
         //if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d
index 2526671..0158c3d 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8863.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8863.d
@@ -46,6 +46,7 @@
         //t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
         //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
         //if wback && n == t then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
@@ -75,6 +76,7 @@
         //t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
         //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
         //if wback && n == t then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldr_A8864.d b/src/arch/arm/v7/opdefs/ldr_A8864.d
index acb6f94..3fbc0e3 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8864.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8864.d
@@ -37,6 +37,13 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_ldr_literal_from_thumb
+        post = post_process_ldr_instructions
+
+    }
+
 }
 
 @encoding(T2) {
@@ -53,9 +60,17 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_ldr_literal_from_thumb
+        post = post_process_ldr_instructions
+
+    }
+
     @rules {
 
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
@@ -65,14 +80,29 @@
 
     @word cond(4) 0 1 0 1 U(1) 0 0 1 1 1 1 1 Rt(4) imm12(12)
 
-    @syntax <Rgt> <label>
+    @syntax {c} <Rgt> <label>
 
     @conv {
 
+        c = Condition(cond)
         Rgt = Register(Rt)
         imm32 = ZeroExtend(imm12, 12, 32)
         label = MakeAccessOffset(U, imm32)
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_ldr_literal_from_arm
+        post = post_process_ldr_instructions
+
+    }
+
+    @rules {
+
+        //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
+
+    }
+
 }
diff --git a/src/arch/arm/v7/opdefs/ldr_A8865.d b/src/arch/arm/v7/opdefs/ldr_A8865.d
index 11a8932..56a09fb 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8865.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8865.d
@@ -67,6 +67,7 @@
         //if Rn == '1111' then SEE LDR (literal);
         //if m IN {13,15} then UNPREDICTABLE;
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldrb_A8867.d b/src/arch/arm/v7/opdefs/ldrb_A8867.d
index 8097fd0..52a50cb 100644
--- a/src/arch/arm/v7/opdefs/ldrb_A8867.d
+++ b/src/arch/arm/v7/opdefs/ldrb_A8867.d
@@ -60,6 +60,7 @@
         //if Rt == '1111' then SEE PLD;
         //if Rn == '1111' then SEE LDRB (literal);
         //if t == 13 then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
@@ -87,6 +88,7 @@
         //if P == '1' && U == '1' && W == '0' then SEE LDRBT;
         //if P == '0' && W == '0' then UNDEFINED;
         //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
@@ -115,6 +117,7 @@
         //if P == '1' && U == '1' && W == '0' then SEE LDRBT;
         //if P == '0' && W == '0' then UNDEFINED;
         //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c
index f85fc91..8895740 100644
--- a/src/arch/arm/v7/post.c
+++ b/src/arch/arm/v7/post.c
@@ -89,3 +89,192 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con
     }
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = accès aux données du binaire d'origine.            *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void post_process_branch_and_link_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format)
+{
+    GArchOperand *op;                       /* Opérande numérique en place */
+    uint32_t addr;                          /* Adresse visée par le saut   */
+    GArchOperand *new;                      /* Instruction de ciblage      */
+    vmpa2t target;
+    mrange_t trange;
+    VMPA_BUFFER(loc);
+    char name[5 + VMPA_MAX_LEN];
+    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+
+    op = g_arch_instruction_get_operand(instr, 0);
+
+    if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr))
+    {
+        new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr);
+
+        if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format))
+        {
+            init_vmpa(&target, VMPA_NO_PHYSICAL, addr);
+            init_mrange(&trange, &target, 0);
+
+            vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL);
+            snprintf(name, sizeof(name), "sub_%s", loc + 2);
+
+            routine = g_binary_routine_new();
+            g_binary_routine_set_name(routine, strdup(name));
+            //routine = try_to_demangle_routine(name);
+
+            g_binary_routine_set_range(routine, &trange);
+
+            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            g_binary_symbol_attach_routine(symbol, routine);
+            g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+
+
+
+            g_target_operand_resolve(G_TARGET_OPERAND(new), format);
+
+        }
+
+        g_arch_instruction_replace_operand(instr, new, op);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = accès aux données du binaire d'origine.            *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format)
+{
+    GArchOperand *op;                       /* Opérande numérique en place */
+    uint32_t addr;                          /* Adresse visée par le saut   */
+    GArchOperand *new;                      /* Instruction de ciblage      */
+    vmpa2t target;
+    mrange_t trange;
+    VMPA_BUFFER(loc);
+    char name[5 + VMPA_MAX_LEN];
+    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+
+    op = g_arch_instruction_get_operand(instr, 1);
+
+    if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr))
+    {
+        new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr);
+
+        if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format))
+        {
+            init_vmpa(&target, VMPA_NO_PHYSICAL, addr);
+            init_mrange(&trange, &target, 0);
+
+            vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL);
+            snprintf(name, sizeof(name), "loc_%s", loc + 2);
+
+            routine = g_binary_routine_new();
+            g_binary_routine_set_name(routine, strdup(name));
+            //routine = try_to_demangle_routine(name);
+
+            g_binary_routine_set_range(routine, &trange);
+
+            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            g_binary_symbol_attach_routine(symbol, routine);
+            g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+
+
+
+            g_target_operand_resolve(G_TARGET_OPERAND(new), format);
+
+        }
+
+        g_arch_instruction_replace_operand(instr, new, op);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = accès aux données du binaire d'origine.            *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format)
+{
+    GArchOperand *op;                       /* Opérande numérique en place */
+    uint32_t addr;                          /* Adresse visée par le saut   */
+    GArchOperand *new;                      /* Instruction de ciblage      */
+    vmpa2t target;
+    mrange_t trange;
+    VMPA_BUFFER(loc);
+    char name[5 + VMPA_MAX_LEN];
+    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+
+    op = g_arch_instruction_get_operand(instr, 1);
+
+    if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr))
+    {
+        new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr);
+
+        if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format))
+        {
+            init_vmpa(&target, VMPA_NO_PHYSICAL, addr);
+            init_mrange(&trange, &target, 0);
+
+            vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL);
+            snprintf(name, sizeof(name), "loc_%s", loc + 2);
+
+            routine = g_binary_routine_new();
+            g_binary_routine_set_name(routine, strdup(name));
+            //routine = try_to_demangle_routine(name);
+
+            g_binary_routine_set_range(routine, &trange);
+
+            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            g_binary_symbol_attach_routine(symbol, routine);
+            g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+
+
+
+            g_target_operand_resolve(G_TARGET_OPERAND(new), format);
+
+        }
+
+        g_arch_instruction_replace_operand(instr, new, op);
+
+    }
+
+}
diff --git a/src/arch/arm/v7/post.h b/src/arch/arm/v7/post.h
index dec51b2..79dcaa8 100644
--- a/src/arch/arm/v7/post.h
+++ b/src/arch/arm/v7/post.h
@@ -33,6 +33,15 @@
 /* Complète un désassemblage accompli pour une instruction. */
 void post_process_branch_instructions(GArchInstruction *, GProcContext *, GBinFormat *);
 
+/* Complète un désassemblage accompli pour une instruction. */
+void post_process_branch_and_link_instructions(GArchInstruction *, GProcContext *, GBinFormat *);
+
+/* Complète un désassemblage accompli pour une instruction. */
+void post_process_comp_and_branch_instructions(GArchInstruction *, GProcContext *, GBinFormat *);
+
+/* Complète un désassemblage accompli pour une instruction. */
+void post_process_ldr_instructions(GArchInstruction *, GProcContext *, GBinFormat *);
+
 
 
 #endif  /* _ARCH_ARM_V7_POST_H */
diff --git a/src/arch/arm/v7/processor.c b/src/arch/arm/v7/processor.c
index d83c36d..3464214 100644
--- a/src/arch/arm/v7/processor.c
+++ b/src/arch/arm/v7/processor.c
@@ -231,8 +231,7 @@ static GArmV7Context *g_armv7_processor_get_context(const GArmV7Processor *proc)
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-#include "link.h"
-#include "post.h"
+
 static GArchInstruction *g_armv7_processor_disassemble(const GArmV7Processor *proc, GArmV7Context *ctx, const bin_t *data, vmpa2t *pos, phys_t end)
 {
     GArchInstruction *result;               /* Instruction à renvoyer      */
@@ -297,11 +296,11 @@ static GArchInstruction *g_armv7_processor_disassemble(const GArmV7Processor *pr
 
     if (result != NULL)
         advance_vmpa(pos, diff);
-
+    /*
     else
         result = g_raw_instruction_new_array(data, MDS_32_BITS, 1, pos, end,
                                              G_ARCH_PROCESSOR(proc)->endianness);
-
+    */
     return result;
 
 }
diff --git a/src/arch/artificial.c b/src/arch/artificial.c
index 9b84226..d2b2117 100644
--- a/src/arch/artificial.c
+++ b/src/arch/artificial.c
@@ -72,9 +72,6 @@ static void g_db_instruction_build_keyword(const GDbInstruction *, AsmSyntax);
 /* Informe sur une éventuelle référence à une autre instruction. */
 static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *, vmpa_t *);
 
-/* Indique si l'instruction correspond à un retour de fonction. */
-static bool g_db_instruction_is_return(const GDbInstruction *);
-
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -134,7 +131,6 @@ static void g_db_instruction_init(GDbInstruction *instr)
     parent = G_ARCH_INSTRUCTION(instr);
 
     parent->get_link = (get_instruction_link_fc)g_db_instruction_get_link;
-    parent->is_return = (is_instruction_return_fc)g_db_instruction_is_return;
 
 }
 
@@ -271,25 +267,6 @@ static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *instr
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : instr = instruction à consulter.                             *
-*                                                                             *
-*  Description : Indique si l'instruction correspond à un retour de fonction. *
-*                                                                             *
-*  Retour      : true si l'instruction est un 'return' quelconque ou false.   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_db_instruction_is_return(const GDbInstruction *instr)
-{
-    return false;
-
-}
-
-
 #ifdef DEBUG
 
 /******************************************************************************
diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c
index 98e29dd..ac1efdc 100644
--- a/src/arch/dalvik/instruction.c
+++ b/src/arch/dalvik/instruction.c
@@ -398,7 +398,7 @@ static void g_dalvik_instruction_init(GDalvikInstruction *instr)
 
     parent->get_rw_regs = (get_instruction_rw_regs_fc)g_dalvik_instruction_get_rw_registers;
     parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link;
-    parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return;
+    //parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return;
     parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile;
 
 }
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 5bdcedb..de9c70d 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -44,9 +44,6 @@ typedef void (* build_instruction_keyword_fc) (const GArchInstruction *, AsmSynt
 /* Informe sur une éventuelle référence à une autre instruction. */
 typedef InstructionLinkType (* get_instruction_link_fc) (const GArchInstruction *, vmpa_t *);
 
-/* Indique si l'instruction correspond à un retour de fonction. */
-typedef bool (* is_instruction_return_fc) (const GArchInstruction *);
-
 
 /* Définition générique d'une instruction d'architecture (instance) */
 struct _GArchInstruction
@@ -71,8 +68,6 @@ struct _GArchInstruction
     vmpa_t address;                         /* Position associée           */
 
     /* ------- %< ----------- */
-
-
     GArchOperand **operands;                /* Liste des opérandes         */
     size_t operands_count;                  /* Nbre. d'opérandes utilisées */
 
@@ -88,9 +83,11 @@ struct _GArchInstruction
     //print_instruction_fc print;             /* Imprime l'ensemble          */
     //get_instruction_keyword_fc get_key;     /* Texte humain équivalent     */
     get_instruction_link_fc get_link;       /* Référence à une instruction */
-    is_instruction_return_fc is_return;     /* Retour de fonction ou pas ? */
+    //is_instruction_return_fc is_return;     /* Retour de fonction ou pas ? */
     decomp_instr_fc decomp;                 /* Procédure de décompilation  */
 
+    bool is_return;                         /* Retour de fonction ou pas ? */
+
 };
 
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 598da6d..67fd184 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -105,6 +105,8 @@ static void g_arch_instruction_init(GArchInstruction *instr)
 {
     DL_LIST_ITEM_INIT(&instr->flow);
 
+    instr->is_return = false;
+
 }
 
 
@@ -475,6 +477,28 @@ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *instr, v
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr  = instruction à consulter.                            *
+*                status = statut de l'instruction vis à vis du flot.          *
+*                                                                             *
+*  Description : Précise si l'instruction correspond à un retour de fonction. *
+*                                                                             *
+*  Retour      : true (pour respecter le prototypage depuis les fichiers D).  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_arch_instruction_define_as_return(GArchInstruction *instr, bool status)
+{
+    instr->is_return = status;
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr = instruction à consulter.                             *
 *                                                                             *
 *  Description : Indique si l'instruction correspond à un retour de fonction. *
@@ -487,7 +511,7 @@ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *instr, v
 
 bool g_arch_instruction_is_return(const GArchInstruction *instr)
 {
-    return instr->is_return(instr);
+    return instr->is_return;
 
 }
 
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index eb31865..02bb9b7 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -156,6 +156,9 @@ typedef union _link_extra_info
 /* Informe sur une éventuelle référence à une autre instruction. */
 InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *, vmpa_t *);
 
+/* Précise si l'instruction correspond à un retour de fonction. */
+bool g_arch_instruction_define_as_return(GArchInstruction *, bool);
+
 /* Indique si l'instruction correspond à un retour de fonction. */
 bool g_arch_instruction_is_return(const GArchInstruction *instr);
 
diff --git a/src/arch/x86/instruction.c b/src/arch/x86/instruction.c
index 0450d96..c26a995 100644
--- a/src/arch/x86/instruction.c
+++ b/src/arch/x86/instruction.c
@@ -496,7 +496,7 @@ static void g_x86_instruction_init(GX86Instruction *instr)
 
     //parent->get_text = (get_instruction_text_fc)x86_get_instruction_text;
     parent->get_link = (get_instruction_link_fc)x86_get_instruction_link;
-    parent->is_return = (is_instruction_return_fc)x86_instruction_is_return;
+    //parent->is_return = (is_instruction_return_fc)x86_instruction_is_return;
 
 }
 
diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am
index e997beb..63ca5fe 100644
--- a/tools/d2c/Makefile.am
+++ b/tools/d2c/Makefile.am
@@ -7,6 +7,7 @@ bin_PROGRAMS = d2c
 
 
 d2c_SOURCES =							\
+	args.h args.c						\
 	bits.h bits.c						\
 	coder.h coder.c						\
 	conv.h conv.c						\
@@ -15,6 +16,7 @@ d2c_SOURCES =							\
 	helpers.h helpers.c					\
 	hooks.h hooks.c						\
 	pproc.h pproc.c						\
+	qckcall.h qckcall.c					\
 	rules.h rules.c						\
 	spec.h spec.c						\
 	syntax.h syntax.c
diff --git a/tools/d2c/args.c b/tools/d2c/args.c
new file mode 100644
index 0000000..616873b
--- /dev/null
+++ b/tools/d2c/args.c
@@ -0,0 +1,1161 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * args.c - gestion des arguments dans leur ensemble
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  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 "args.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "conv.h"
+#include "helpers.h"
+
+
+
+/*
+#include <assert.h>
+#include <ctype.h>
+
+#include <regex.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+
+*/
+
+
+
+
+/* Types d'expressions représentés */
+typedef enum _ConvExprType
+{
+    CET_NAME,                               /* Désignation de variable     */
+    CET_NUMBER,                             /* Valeur codée en dur         */
+    CET_COMPOSED,                           /* Agrégat de champs divers    */
+    CET_UNARY,                              /* Opération unaire            */
+    CET_BINARY,                             /* Opération binaire           */
+
+    CET_COUNT
+
+} ConvExprType;
+
+
+/* Représentation d'une expression de conversion */
+struct _arg_expr_t
+{
+    ConvExprType type;
+
+    bool declared;                          /* Expression déjà déclarée ?  */
+    bool defined;                           /* Expression déjà définie ?   */
+
+    union
+    {
+        /* CET_NAME */
+        char *name;                         /* Désignation de variable     */
+
+        /* CET_NUMBER */
+        unsigned long number;               /* Valeur durablement définie  */
+
+        /* CET_COMPOSED */
+        struct
+        {
+            char **comp_items;              /* Elements à agréger          */
+            size_t comp_count;              /* Quantité de ces éléments    */
+        };
+
+        /* CET_UNARY */
+        struct
+        {
+            arg_expr_t *un_expr;            /* Expression à traiter        */
+            ConvUnaryOperation un_op;       /* Type d'opération à mener    */
+
+        };
+
+        /* CET_BINARY */
+        struct
+        {
+            arg_expr_t *bin_expr1;          /* Expression à traiter        */
+            arg_expr_t *bin_expr2;          /* Expression à traiter        */
+            ConvBinaryOperation bin_op;     /* Type d'opération à mener    */
+
+        };
+
+    };
+
+};
+
+
+/* Visite une expression en traitant en premier ses composantes. */
+typedef bool (* visit_expr_fc) (arg_expr_t *, int, const coding_bits *, const conv_list *, void *);
+
+/* Visite une expression en traitant en premier ses composantes. */
+static bool visit_arg_expr(arg_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *);
+
+/* Retrouve si elle existe une variable manipulée. */
+static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **);
+
+
+
+/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */
+
+
+/* Liste d'expressions utilisées en arguments de conversion */
+struct _arg_list_t
+{
+    arg_expr_t **items;                     /* Liste d'expressions         */
+    size_t count;                           /* Taille de cette liste       */
+
+};
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            REPRESENTATION D'UN ARGUMENT                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : name = désignation d'une variable quelconque.                *
+*                                                                             *
+*  Description : Référence une variable en tant qu'expression de conversion.  *
+*                                                                             *
+*  Retour      : Nouvelle expression mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_expr_t *build_arg_expr_from_name(char *name)
+{
+    arg_expr_t *result;                     /* Structure à retourner       */
+
+    result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+    result->type = CET_NAME;
+
+    result->name = make_string_lower(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : number = valeur à conserver dans sa forme brute.             *
+*                                                                             *
+*  Description : Conserve une valeur en tant qu'expression de conversion.     *
+*                                                                             *
+*  Retour      : Nouvelle expression mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_expr_t *build_arg_expr_from_number(unsigned long number)
+{
+    arg_expr_t *result;                     /* Structure à retourner       */
+
+    result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+    result->type = CET_NUMBER;
+
+    result->number = number;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item1 = premier élément à agréger.                           *
+*                item2 = second élément à agréger.                            *
+*                                                                             *
+*  Description : Construit une base d'expression de conversion composée.      *
+*                                                                             *
+*  Retour      : Nouvelle expression mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_expr_t *build_composed_arg_expr(char *item1, char *item2)
+{
+    arg_expr_t *result;                     /* Structure à retourner       */
+
+    result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+    result->type = CET_COMPOSED;
+
+    result->comp_items = (char **)calloc(2, sizeof(char *));
+    result->comp_count = 2;
+
+    result->comp_items[0] = make_string_lower(item1);
+    result->comp_items[1] = make_string_lower(item2);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = expression déjà en place à compléter.                 *
+*                item = nouvel élément à agréger.                             *
+*                                                                             *
+*  Description : Etend une base d'expression de conversion composée.          *
+*                                                                             *
+*  Retour      : Expression en place et mise à jour.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_expr_t *extend_composed_arg_expr(arg_expr_t *expr, char *item)
+{
+    assert(expr->type == CET_COMPOSED);
+
+    expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *));
+
+    expr->comp_items[expr->comp_count - 1] = make_string_lower(item);
+
+    return expr;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = expression à encapsuler.                              *
+*                op   = opération unaire à associer à l'opération.            *
+*                                                                             *
+*  Description : Traduit une opération unaire sur expression de conversion.   *
+*                                                                             *
+*  Retour      : Nouvelle expression mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_expr_t *build_unary_arg_expr(arg_expr_t *expr, ConvUnaryOperation op)
+{
+    arg_expr_t *result;                     /* Structure à retourner       */
+
+    result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+    result->type = CET_UNARY;
+
+    result->un_expr = expr;
+    result->un_op = op;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr1 = première expression à encapsuler.                    *
+*                expr2 = seconde expression à encapsuler.                     *
+*                op    = opération binaire à associer à l'opération.          *
+*                                                                             *
+*  Description : Traduit une opération binaire sur expression de conversion.  *
+*                                                                             *
+*  Retour      : Nouvelle expression mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_expr_t *build_binary_arg_expr(arg_expr_t *expr1, arg_expr_t *expr2, ConvBinaryOperation op)
+{
+    arg_expr_t *result;                    /* Structure à retourner       */
+
+    result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+    result->type = CET_BINARY;
+
+    result->bin_expr1 = expr1;
+    result->bin_expr2 = expr2;
+    result->bin_op = op;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = expression à libérer de la mémoire.                   *
+*                                                                             *
+*  Description : Supprime tous les éléments mis en place pour un argument.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void delete_arg_expr(arg_expr_t *expr)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    switch (expr->type)
+    {
+        case CET_NAME:
+            free(expr->name);
+            break;
+
+        case CET_COMPOSED:
+            for (i = 0; i < expr->comp_count; i++)
+                free(expr->comp_items[i]);
+            free(expr->comp_items);
+            break;
+
+        case CET_UNARY:
+            delete_arg_expr(expr->un_expr);
+            break;
+
+        case CET_BINARY:
+            delete_arg_expr(expr->bin_expr1);
+            delete_arg_expr(expr->bin_expr2);
+            break;
+
+        default:
+            break;
+
+    }
+
+    free(expr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première expression à consulter.                      *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                size = taille déterminée avec précision. [OUT]               *
+*                                                                             *
+*  Description : Détermine la taille en bits d'une expression donnée.         *
+*                                                                             *
+*  Retour      : true si la taille a pu être déterminée, false sinon.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool compute_arg_expr_size(const arg_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size)
+{
+    bool result;                            /* Bilan à retourner           */
+    raw_bitfield *field;                    /* Eventuel champ brut associé */
+    conv_func *func;                        /* Eventuelle fonction liée    */
+    size_t i;                               /* Boucle de parcours          */
+    unsigned int tmp;                       /* Stockage temporaire         */
+
+    switch (expr->type)
+    {
+        case CET_NAME:
+
+            result = find_var_by_name(bits, list, expr->name, &field, &func);
+
+            if (result)
+            {
+                if (field != NULL)
+                    *size = get_raw_bitfield_length(field);
+                else
+                    result = compute_conv_func_size(func, bits, list, size);
+            }
+
+            break;
+
+        case CET_COMPOSED:
+
+            result = true;
+            *size = 0;
+
+            for (i = 0; i < expr->comp_count && result; i++)
+            {
+                if (isdigit(expr->comp_items[i][0]))
+                    *size += strlen(expr->comp_items[i]);
+
+                else
+                {
+                    if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func))
+                        result = false;
+
+                    else
+                    {
+                        if (field != NULL)
+                            *size += get_raw_bitfield_length(field);
+                        else
+                        {
+                            result = compute_conv_func_size(func, bits, list, &tmp);
+                            *size += tmp;
+                        }
+                    }
+
+                }
+
+            }
+
+            break;
+
+        case CET_UNARY:
+            result = compute_arg_expr_size(expr->un_expr, bits, list, size);
+            break;
+
+        case CET_BINARY:
+
+            result = compute_arg_expr_size(expr->bin_expr1, bits, list, &tmp);
+
+            if (result)
+                result = compute_arg_expr_size(expr->bin_expr1, bits, list, size);
+
+            if (tmp > *size) *size = tmp;
+
+            break;
+
+        default:
+            result = false;
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première expression à encapsuler.                     *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                data = éventuelle donnée à transmettre à chaque visite.      *
+*                                                                             *
+*  Description : Visite une expression en traitant en premier ses composantes.*
+*                                                                             *
+*  Retour      : Bilan des traitements effectués.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool visit_arg_expr(arg_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    switch (expr->type)
+    {
+        case CET_UNARY:
+            result = visit_arg_expr(expr->un_expr, visit, fd, bits, list, data);
+            break;
+
+        case CET_BINARY:
+            result = visit_arg_expr(expr->bin_expr1, visit, fd, bits, list, data);
+            result = visit_arg_expr(expr->bin_expr2, visit, fd, bits, list, data);
+            break;
+
+        default:
+            result = true;
+            break;
+
+    }
+
+    result &= visit(expr, fd, bits, list, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bits  = gestionnaire des bits d'encodage.                    *
+*                list  = liste de l'ensemble des fonctions de conversion.     *
+*                name  = déssignation de la variable recherchée.              *
+*                field = éventuel élement brut de décodage.                   *
+*                func  = éventuelle fonction de conversion pour intermédiaire.*
+*                                                                             *
+*  Description : Retrouve si elle existe une variable manipulée.              *
+*                                                                             *
+*  Retour      : Bilan des recherches : trouvaille ou non ?                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func)
+{
+    bool result;                            /* Bilan à retourner           */
+    raw_bitfield *cached_field;             /* Champ, version cachée       */
+    conv_func *cached_func;                 /* Fonction, version cachée    */
+
+    cached_field = find_named_field_in_bits(bits, name);
+    result = (cached_field != NULL);
+
+    if (!result)
+    {
+        cached_func = find_named_conv_in_list(list, name);
+        result = (cached_func != NULL);
+    }
+    else
+        cached_func = NULL;
+
+    if (field != NULL) *field = cached_field;
+    if (func != NULL) *func = cached_func;
+
+    if (!result)
+        fprintf(stderr, "Variable '%s' not found!\n", name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première expression à encapsuler.                     *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                                                                             *
+*  Description : S'assure du marquage des expressions pre-requises.           *
+*                                                                             *
+*  Retour      : Bilan des traitements effectués.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_arg_expr_content_fully_marked(arg_expr_t *expr, const coding_bits *bits, const conv_list *list)
+{
+    bool mark_sub_expr(arg_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused)
+    {
+        bool result;                        /* Bilan à retourner           */
+        size_t i;                           /* Boucle de parcours          */
+
+        bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name)
+        {
+            bool found;                     /* Bilan d'opération à renvoyer*/
+            raw_bitfield *field;            /* Eventuel champ brut associé */
+            conv_func *func;                /* Eventuelle fonction liée    */
+
+            found = find_var_by_name(bts, lst, name, &field, &func);
+
+            if (found)
+            {
+                if (field != NULL)
+                    mark_raw_bitfield_as_used(field);
+                else /*if (func != NULL) */
+                    mark_conv_func(func, bts, lst);
+
+                printf(" VAR '%s' found (bf=%d  fc=%d)\n", name, !!field, !!func);
+
+
+            }
+            else printf(" VAR '%s' not found...\n", name);
+
+            return found;
+
+        }
+
+        /* Il est uniquement nécessaire de s'attacher aux références */
+        switch (sub->type)
+        {
+            case CET_NAME:
+                result = mark_by_name(bits, lst, sub->name);
+                break;
+
+            case CET_COMPOSED:
+                result = true;
+                for (i = 0; i < sub->comp_count && result; i++)
+                    if (!isdigit(sub->comp_items[i][0]))
+                        result = mark_by_name(bits, lst, sub->comp_items[i]);
+                break;
+
+            default:
+                result = true;
+                break;
+
+        }
+
+        return result;
+
+    }
+
+    return visit_arg_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première expression à encapsuler.                     *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                arch = architecture visée par l'opération globale.           *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                wide = taille des mots décodés.                              *
+*                                                                             *
+*  Description : S'assure de la déclaration des expressions pre-requises.     *
+*                                                                             *
+*  Retour      : Bilan des traitements effectués.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_arg_expr_content_fully_declared(arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+    bool declare_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide)
+    {
+        bool result;                        /* Bilan à retourner           */
+        size_t i;                           /* Boucle de parcours          */
+
+        /* Si l'expression a déjà été définie lors d'un précédent besoin... */
+        printf("  sub declared ? %d  --  type = %d\n", sub->declared, sub->type);
+        if (sub->declared) return true;
+
+        bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name)
+        {
+            bool found;                     /* Bilan d'opération à renvoyer*/
+            conv_func *func;                /* Eventuelle fonction liée    */
+
+            found = find_var_by_name(bts, lst, name, NULL, &func);
+
+            if (found && func != NULL)
+            {
+                printf("========= DECLARE for '%s'\n", name);
+                found = declare_conv_func(func, _f, _bts, _lst, _wide);
+                printf("========= END DECLARE for '%s'\n", name);
+
+                /**
+                 * Si on déclare les variables suivantes dans declare_conv_func(),
+                 * elles seront également déclarées pour les fonctions de conversion
+                 * racine à partir de declare_syntax_items(), ce qui ne convient pas
+                 * car les appels racine servent directement d'arguments.
+                 */
+
+                if (is_conv_func_expression(func))
+                    dprintf(_f, "\t\tuint%u_t val_%s; // Ho\n", _wide, name);
+                else
+                    dprintf(_f, "\t\tGArchOperand *val_%s;;;;;\n", name);
+
+            }
+
+            return found;
+
+        }
+
+        /* Il est uniquement nécessaire de s'attacher aux références */
+        switch (sub->type)
+        {
+            case CET_NAME:
+                result = declare_by_name(f, bits, lst, *wide, sub->name);
+                break;
+
+            case CET_COMPOSED:
+                result = true;
+                for (i = 0; i < sub->comp_count && result; i++)
+                    if (!isdigit(sub->comp_items[i][0]))
+                        printf("... trying to declare... '%s'\n", sub->comp_items[i]);
+                for (i = 0; i < sub->comp_count && result; i++)
+                    if (!isdigit(sub->comp_items[i][0]))
+                        result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]);
+                break;
+
+            default:
+                result = true;
+                break;
+
+        }
+
+        sub->declared = result;
+
+        return result;
+
+    }
+
+    return visit_arg_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première expression à encapsuler.                     *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                arch = architecture visée par l'opération globale.           *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                pp   = pré-processeur pour les échanges de chaînes.          *
+*                                                                             *
+*  Description : S'assure de la définition des expressions pre-requises.      *
+*                                                                             *
+*  Retour      : Bilan des traitements effectués.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_arg_expr_content_fully_defined(arg_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+    typedef struct _def_info
+    {
+        const char *arch;
+        const pre_processor *pp;
+
+    } def_info;
+
+    def_info info;                          /* Transmissions au visiteur   */
+
+    bool define_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info)
+    {
+        bool result;                        /* Bilan à retourner           */
+        size_t i;                           /* Boucle de parcours          */
+
+        /* Si l'expression a déjà été définie lors d'un précédent besoin... */
+        if (sub->defined) return true;
+
+        bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name)
+        {
+            bool found;                     /* Bilan d'opération à renvoyer*/
+            conv_func *func;                /* Eventuelle fonction liée    */
+
+            found = find_var_by_name(bts, lst, name, NULL, &func);
+
+            if (found && func != NULL)
+                found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp);
+
+            return found;
+
+        }
+
+        /* Il est uniquement nécessaire de s'attacher aux références */
+        switch (sub->type)
+        {
+            case CET_NAME:
+                result = define_by_name(f, bits, lst, info, sub->name);
+                break;
+
+            case CET_COMPOSED:
+                result = true;
+                for (i = 0; i < sub->comp_count && result; i++)
+                    if (!isdigit(sub->comp_items[i][0]))
+                        result = define_by_name(f, bits, lst, info, sub->comp_items[i]);
+                break;
+
+            default:
+                result = true;
+                break;
+
+        }
+
+        sub->defined = result;
+
+        return result;
+
+    }
+
+    info.arch = arch;
+    info.pp = pp;
+
+    return visit_arg_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = première expression à encapsuler.                     *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                                                                             *
+*  Description : Définit une expression utilisée dans une conversion.         *
+*                                                                             *
+*  Retour      : Bilan des traitements effectués.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list)
+{
+    bool result;                            /* Bilan à retourner           */
+    raw_bitfield *field;                    /* Eventuel champ brut associé */
+    conv_func *func;                        /* Eventuelle fonction liée    */
+    unsigned int max_size;                  /* Quantité de bits totale     */
+    size_t i;                               /* Boucle de parcours          */
+    const char *cname;                      /* Raccourci de confort        */
+    unsigned int used_size;                 /* Quantité de bits utilisée   */
+
+    result = true;
+
+    switch (expr->type)
+    {
+        case CET_NAME:
+
+            if (!find_var_by_name(bits, list, expr->name, &field, &func))
+                result = false;
+
+            else
+            {
+                if (field != NULL)
+                    dprintf(fd, "raw_%s", expr->name);
+                else
+                    dprintf(fd, "val_%s", expr->name);
+            }
+
+            break;
+
+        case CET_NUMBER:
+            dprintf(fd, "%lu", expr->number);
+            break;
+
+        case CET_COMPOSED:
+
+            result = compute_arg_expr_size(expr, bits, list, &max_size);
+
+            printf("MAX SIZE :: %u\n", max_size);
+
+            for (i = 0; i < expr->comp_count && result; i++)
+            {
+                cname = expr->comp_items[i];
+
+                if (i > 0)
+                    dprintf(fd, " | ");
+
+                /* Constante binaire ? */
+                if (isdigit(cname[0]))
+                {
+                    max_size -= strlen(cname);
+
+                    if (max_size == 0)
+                        dprintf(fd, "b%s", cname);
+                    else
+                        dprintf(fd, "b%s << %u", cname, max_size);
+
+                }
+
+                /* Ou variable définie ? */
+                else
+                {
+                    result = find_var_by_name(bits, list, cname, &field, &func);
+
+                    if (result)
+                    {
+                        if (field != NULL)
+                            used_size = get_raw_bitfield_length(field);
+                        else
+                            /*result = */compute_conv_func_size(func, bits, list, &used_size);
+
+                        max_size -= used_size;
+
+                        if (field != NULL)
+                        {
+                            if (max_size == 0)
+                                dprintf(fd, "raw_%s", cname);
+                            else
+                                dprintf(fd, "raw_%s << %u", cname, max_size);
+                        }
+                        else
+                        {
+                            if (max_size == 0)
+                                dprintf(fd, "val_%s", cname);
+                            else
+                                dprintf(fd, "val_%s << %u", cname, max_size);
+                        }
+
+                    }
+
+                }
+
+            }
+
+            break;
+
+        case CET_UNARY:
+
+            switch (expr->un_op)
+            {
+                case CUO_NOT:
+                    dprintf(fd, "!");
+                    break;
+                default:
+                    result = false;
+                    break;
+            }
+
+            result &= define_arg_expr(expr->un_expr, fd, bits, list);
+
+            break;
+
+        case CET_BINARY:
+
+            dprintf(fd, "(");
+
+            result = define_arg_expr(expr->bin_expr1, fd, bits, list);
+
+            switch (expr->bin_op)
+            {
+                case CBO_EOR:
+                    dprintf(fd, " ^ ");
+                    break;
+                default:
+                    result = false;
+                    break;
+            }
+
+            result &= define_arg_expr(expr->bin_expr2, fd, bits, list);
+
+            dprintf(fd, ")");
+
+            break;
+
+        default:
+            result = false;
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         MANIPULATION DE LISTES D'ARGUMENTS                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = expression initial pour constituer une liste.         *
+*                                                                             *
+*  Description : Crée une liste d'arguments de conversion.                    *
+*                                                                             *
+*  Retour      : Nouvelle structure mise en place.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_list_t *build_arg_list(arg_expr_t *expr)
+{
+    arg_list_t *result;                     /* Structure à retourner       */
+
+    result = (arg_list_t *)calloc(1, sizeof(arg_list_t));
+
+    result->items = (arg_expr_t **)calloc(1, sizeof(arg_expr_t *));
+    result->count = 1;
+
+    result->items[0] = expr;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = liste d'expressions à supprimer de la mémoire.        *
+*                                                                             *
+*  Description : Libère la mémoire occupée par une liste d'expressions.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void delete_arg_list(arg_list_t *list)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < list->count; i++)
+        delete_arg_expr(list->items[i]);
+
+    if (list->items != NULL)
+        free(list->items);
+
+    free(list);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = liste d'expressions à supprimer de la mémoire. [OUT]  *
+*                expr = expression à ajouter à la liste courante.             *
+*                                                                             *
+*  Description : Ajoute un élément à une liste d'arguments de conversion.     *
+*                                                                             *
+*  Retour      : Structure en place mise à jour.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+arg_list_t *extend_arg_list(arg_list_t *list, arg_expr_t *expr)
+{
+    list->items = (arg_expr_t **)realloc(list->items, ++list->count * sizeof(arg_expr_t *));
+
+    list->items[list->count - 1] = expr;
+
+    return list;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                                                                             *
+*  Description : S'assure du marquage des expressions pre-requises.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_arg_list_content_fully_marked(arg_list_t *args, const coding_bits *bits, const conv_list *list)
+{
+    bool result;                            /* Bilan à remonter            */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < args->count && result; i++)
+        result = ensure_arg_expr_content_fully_marked(args->items[i], bits, list);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                wide = taille des mots décodés.                              *
+*                                                                             *
+*  Description : S'assure de la déclaration des expressions pre-requises.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_arg_list_content_fully_declared(arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+    bool result;                            /* Bilan à remonter            */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < args->count && result; i++)
+        result = ensure_arg_expr_content_fully_declared(args->items[i], fd, bits, list, wide);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                arch = architecture visée par l'opération globale.           *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                pp   = pré-processeur pour les échanges de chaînes.          *
+*                                                                             *
+*  Description : S'assure de la définition des expressions pre-requises.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_arg_list_content_fully_defined(arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+    bool result;                            /* Bilan à remonter            */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < args->count && result; i++)
+        result = ensure_arg_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                bits = gestionnaire des bits d'encodage.                     *
+*                list = liste de l'ensemble des fonctions de conversion.      *
+*                                                                             *
+*  Description : Définit les variables associées à un appel de fonction.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_arg_list(const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list)
+{
+    bool result;                            /* Bilan à remonter            */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < args->count && result; i++)
+    {
+        if (i > 0) dprintf(fd, ", ");
+        result = define_arg_expr(args->items[i], fd, bits, list);
+    }
+
+    return result;
+
+}
diff --git a/tools/d2c/args.h b/tools/d2c/args.h
new file mode 100644
index 0000000..0ad022e
--- /dev/null
+++ b/tools/d2c/args.h
@@ -0,0 +1,131 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * args.h - prototypes pour la gestion des arguments dans leur ensemble
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  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 _TOOLS_ARGS_H
+#define _TOOLS_ARGS_H
+
+
+#include "bits.h"
+#include "pproc.h"
+
+
+/* Liste des fonctions de conversions présentes */
+typedef struct _conv_list conv_list;
+
+
+
+/* -------------------------- REPRESENTATION D'UN ARGUMENT -------------------------- */
+
+
+/* Types d'opérations unaires */
+typedef enum _ConvUnaryOperation
+{
+    CUO_NOT,                                /* NOT (booléen)               */
+
+    CUO_COUNT
+
+} ConvUnaryOperation;
+
+/* Types d'opérations binaires */
+typedef enum _ConvBinaryOperation
+{
+    CBO_EOR,                                /* Ou exclusif (booléen)       */
+
+    CBO_COUNT
+
+} ConvBinaryOperation;
+
+
+/* Représentation d'une expression de conversion */
+typedef struct _arg_expr_t arg_expr_t;
+
+
+/* Référence une variable en tant qu'expression de conversion. */
+arg_expr_t *build_arg_expr_from_name(char *);
+
+/* Conserve une valeur en tant qu'expression de conversion. */
+arg_expr_t *build_arg_expr_from_number(unsigned long );
+
+/* Construit une base d'expression de conversion composée. */
+arg_expr_t *build_composed_arg_expr(char *, char *);
+
+/* Etend une base d'expression de conversion composée. */
+arg_expr_t *extend_composed_arg_expr(arg_expr_t *, char *);
+
+/* Traduit une opération unaire sur expression de conversion. */
+arg_expr_t *build_unary_arg_expr(arg_expr_t *, ConvUnaryOperation);
+
+/* Traduit une opération binaire sur expression de conversion. */
+arg_expr_t *build_binary_arg_expr(arg_expr_t *, arg_expr_t *, ConvBinaryOperation);
+
+/* Supprime tous les éléments mis en place pour un argument. */
+void delete_arg_expr(arg_expr_t *);
+
+/* Détermine la taille en bits d'une expression donnée. */
+bool compute_arg_expr_size(const arg_expr_t *, const coding_bits *, const conv_list *, unsigned int *);
+
+/* S'assure du marquage des expressions pre-requises. */
+bool ensure_arg_expr_content_fully_marked(arg_expr_t *, const coding_bits *, const conv_list *);
+
+/* S'assure de la déclaration des expressions pre-requises. */
+bool ensure_arg_expr_content_fully_declared(arg_expr_t *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* S'assure de la définition des expressions pre-requises. */
+bool ensure_arg_expr_content_fully_defined(arg_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+/* Définit une expression utilisée dans une conversion. */
+bool define_arg_expr(const arg_expr_t *, int, const coding_bits *, const conv_list *);
+
+
+
+/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */
+
+
+/* Liste d'expressions utilisées en arguments de conversion */
+typedef struct _arg_list_t arg_list_t;
+
+
+/* Crée une liste d'arguments de conversion. */
+arg_list_t *build_arg_list(arg_expr_t *);
+
+/* Libère la mémoire occupée par une liste d'expressions. */
+void delete_arg_list(arg_list_t *);
+
+/* Ajoute un élément à une liste d'arguments de conversion. */
+arg_list_t *extend_arg_list(arg_list_t *, arg_expr_t *);
+
+/* S'assure du marquage des expressions pre-requises. */
+bool ensure_arg_list_content_fully_marked(arg_list_t *, const coding_bits *, const conv_list *);
+
+/* S'assure de la déclaration des expressions pre-requises. */
+bool ensure_arg_list_content_fully_declared(arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* S'assure de la définition des expressions pre-requises. */
+bool ensure_arg_list_content_fully_defined(arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+/* Définit les variables associées à un appel de fonction. */
+bool define_arg_list(const arg_list_t *, int, const coding_bits *, const conv_list *);
+
+
+
+#endif  /* _TOOLS_ARGS_H */
diff --git a/tools/d2c/conv.c b/tools/d2c/conv.c
index e103c93..9947593 100644
--- a/tools/d2c/conv.c
+++ b/tools/d2c/conv.c
@@ -27,1164 +27,55 @@
 #include <assert.h>
 #include <ctype.h>
 #include <malloc.h>
-#include <regex.h>
 #include <stdbool.h>
 #include <string.h>
-#include <sys/param.h>
 
 
 #include "helpers.h"
+#include "qckcall.h"
 
 
 
+/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */
 
 
-/* Types d'expressions représentés */
-typedef enum _ConvExprType
-{
-    CET_NAME,                               /* Désignation de variable     */
-    CET_NUMBER,                             /* Valeur codée en dur         */
-    CET_COMPOSED,                           /* Agrégat de champs divers    */
-    CET_UNARY,                              /* Opération unaire            */
-    CET_BINARY,                             /* Opération binaire           */
-
-    CET_COUNT
-
-} ConvExprType;
-
-
-/* Représentation d'une expression de conversion */
-struct _conv_expr_t
-{
-    ConvExprType type;
-
-    bool declared;                          /* Expression déjà déclarée ?  */
-    bool defined;                           /* Expression déjà définie ?   */
-
-    union
-    {
-        /* CET_NAME */
-        char *name;                         /* Désignation de variable     */
-
-        /* CET_NUMBER */
-        unsigned long number;               /* Valeur durablement définie  */
-
-        /* CET_COMPOSED */
-        struct
-        {
-            char **comp_items;              /* Elements à agréger          */
-            size_t comp_count;              /* Quantité de ces éléments    */
-        };
-
-        /* CET_UNARY */
-        struct
-        {
-            conv_expr_t *un_expr;           /* Expression à traiter        */
-            ConvUnaryOperation un_op;       /* Type d'opération à mener    */
-
-        };
-
-        /* CET_BINARY */
-        struct
-        {
-            conv_expr_t *bin_expr1;         /* Expression à traiter        */
-            conv_expr_t *bin_expr2;         /* Expression à traiter        */
-            ConvBinaryOperation bin_op;     /* Type d'opération à mener    */
-
-        };
-
-    };
-
-};
-
-
-/* Visite une expression en traitant en premier ses composantes. */
-typedef bool (* visit_expr_fc) (conv_expr_t *, int, const coding_bits *, const conv_list *, void *);
-
-
-/* Détermine la taille en bits d'une expression donnée. */
-static bool compute_conv_expr_size(const conv_expr_t *, const coding_bits *, const conv_list *, unsigned int *);
-
-/* Visite une expression en traitant en premier ses composantes. */
-static bool visit_conv_expr(conv_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *);
-
-/* Retrouve si elle existe une variable manipulée. */
-static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **);
-
-/* S'assure du marquage des expressions pre-requises. */
-static bool ensure_conv_expr_content_fully_marked(conv_expr_t *, const coding_bits *, const conv_list *);
-
-/* S'assure de la déclaration des expressions pre-requises. */
-static bool ensure_conv_expr_content_fully_declared(conv_expr_t *, int, const coding_bits *, const conv_list *, unsigned int);
-
-/* S'assure de la définition des expressions pre-requises. */
-static bool ensure_conv_expr_content_fully_defined(conv_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
-
-/* Définit une expression utilisée dans une conversion. */
-static bool define_conv_expr(conv_expr_t *, int, const coding_bits *, const conv_list *);
-
-
-
-/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */
-
-
-/* Liste d'expressions utilisées en arguments de conversion */
-struct _conv_arg_list_t
-{
-    conv_expr_t **items;                    /* Liste d'expressions         */
-    size_t count;                           /* Taille de cette liste       */
-
-};
-
-
-/* S'assure du marquage des expressions pre-requises. */
-static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *, const coding_bits *, const conv_list *);
-
-/* S'assure de la déclaration des expressions pre-requises. */
-static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int);
-
-/* S'assure de la définition des expressions pre-requises. */
-static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
-
-/* Définit les variables associées à un appel de fonction. */
-static bool define_arg_list(conv_arg_list_t *, int, const coding_bits *, const conv_list *);
-
-
-
-/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */
-
-
-/* Fonction de conversion */
-struct _conv_func
-{
-    bool declared;                          /* Expression déjà déclarée ?  */
-    bool defined;                           /* Expression déjà définie ?   */
-
-    char *dest;                             /* Variable de destination     */
-
-    bool is_expr;                           /* Choix du contenu réel       */
-
-    union
-    {
-        conv_expr_t *expr;                  /* Valeur expressive directe   */
-
-        struct
-        {
-            char *name;                     /* Fonction de conversion      */
-            conv_arg_list_t *args;          /* Liste des arguments         */
-
-        };
-
-    };
-
-};
-
-
-/* Détermine la taille en bits du résultat d'une fonction. */
-static bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *);
-
-
-
-
-
-
-#define delete_conv_expr(e)
-
-
-
-
-
-
-/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
-
-
-/* Liste des fonctions de conversions présentes */
-struct _conv_list
-{
-    conv_func **functions;                 /* Fonctions de conversion     */
-    size_t func_count;                     /* Nombre de ces fonctions     */
-
-};
-
-
-
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : name = désignation d'une variable quelconque.                *
-*                                                                             *
-*  Description : Référence une variable en tant qu'expression de conversion.  *
-*                                                                             *
-*  Retour      : Nouvelle expression mise en place.                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_expr_t *build_conv_expr_from_name(char *name)
-{
-    conv_expr_t *result;                    /* Structure à retourner       */
-
-    result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
-    result->type = CET_NAME;
-
-    result->name = make_string_lower(name);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : number = valeur à conserver dans sa forme brute.             *
-*                                                                             *
-*  Description : Conserve une valeur en tant qu'expression de conversion.     *
-*                                                                             *
-*  Retour      : Nouvelle expression mise en place.                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_expr_t *build_conv_expr_from_number(unsigned long number)
-{
-    conv_expr_t *result;                    /* Structure à retourner       */
-
-    result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
-    result->type = CET_NUMBER;
-
-    result->number = number;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : item1 = premier élément à agréger.                           *
-*                item2 = second élément à agréger.                            *
-*                                                                             *
-*  Description : Construit une base d'expression de conversion composée.      *
-*                                                                             *
-*  Retour      : Nouvelle expression mise en place.                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_expr_t *build_composed_conv_expr(char *item1, char *item2)
-{
-    conv_expr_t *result;                    /* Structure à retourner       */
-
-    result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
-    result->type = CET_COMPOSED;
-
-    result->comp_items = (char **)calloc(2, sizeof(char *));
-    result->comp_count = 2;
-
-    result->comp_items[0] = make_string_lower(item1);
-    result->comp_items[1] = make_string_lower(item2);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = expression déjà en place à compléter.                 *
-*                item = nouvel élément à agréger.                             *
-*                                                                             *
-*  Description : Etend une base d'expression de conversion composée.          *
-*                                                                             *
-*  Retour      : Expression en place et mise à jour.                          *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_expr_t *extend_composed_conv_expr(conv_expr_t *expr, char *item)
-{
-    assert(expr->type == CET_COMPOSED);
-
-    expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *));
-
-    expr->comp_items[expr->comp_count - 1] = make_string_lower(item);
-
-    return expr;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = expression à encapsuler.                              *
-*                op   = opération unaire à associer à l'opération.            *
-*                                                                             *
-*  Description : Traduit une opération unaire sur expression de conversion.   *
-*                                                                             *
-*  Retour      : Nouvelle expression mise en place.                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_expr_t *build_unary_conv_expr(conv_expr_t *expr, ConvUnaryOperation op)
-{
-    conv_expr_t *result;                    /* Structure à retourner       */
-
-    result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
-    result->type = CET_UNARY;
-
-    result->un_expr = expr;
-    result->un_op = op;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr1 = première expression à encapsuler.                    *
-*                expr2 = seconde expression à encapsuler.                     *
-*                op    = opération binaire à associer à l'opération.          *
-*                                                                             *
-*  Description : Traduit une opération binaire sur expression de conversion.  *
-*                                                                             *
-*  Retour      : Nouvelle expression mise en place.                           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_expr_t *build_binary_conv_expr(conv_expr_t *expr1, conv_expr_t *expr2, ConvBinaryOperation op)
-{
-    conv_expr_t *result;                    /* Structure à retourner       */
-
-    result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
-    result->type = CET_BINARY;
-
-    result->bin_expr1 = expr1;
-    result->bin_expr2 = expr2;
-    result->bin_op = op;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = première expression à consulter.                      *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                size = taille déterminée avec précision. [OUT]               *
-*                                                                             *
-*  Description : Détermine la taille en bits d'une expression donnée.         *
-*                                                                             *
-*  Retour      : true si la taille a pu être déterminée, false sinon.         *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool compute_conv_expr_size(const conv_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size)
-{
-    bool result;                            /* Bilan à retourner           */
-    raw_bitfield *field;                    /* Eventuel champ brut associé */
-    conv_func *func;                        /* Eventuelle fonction liée    */
-    size_t i;                               /* Boucle de parcours          */
-    unsigned int tmp;                       /* Stockage temporaire         */
-
-    switch (expr->type)
-    {
-        case CET_NAME:
-
-            result = find_var_by_name(bits, list, expr->name, &field, &func);
-
-            if (result)
-            {
-                if (field != NULL)
-                    *size = get_raw_bitfield_length(field);
-                else
-                    result = compute_conv_func_size(func, bits, list, size);
-            }
-
-            break;
-
-        case CET_COMPOSED:
-
-            result = true;
-            *size = 0;
-
-            for (i = 0; i < expr->comp_count && result; i++)
-            {
-                if (isdigit(expr->comp_items[i][0]))
-                    *size += strlen(expr->comp_items[i]);
-
-                else
-                {
-                    if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func))
-                        result = false;
-
-                    else
-                    {
-                        if (field != NULL)
-                            *size += get_raw_bitfield_length(field);
-                        else
-                        {
-                            result = compute_conv_func_size(func, bits, list, &tmp);
-                            *size += tmp;
-                        }
-                    }
-
-                }
-
-            }
-
-            break;
-
-        case CET_UNARY:
-            result = compute_conv_expr_size(expr->un_expr, bits, list, size);
-            break;
-
-        case CET_BINARY:
-
-            result = compute_conv_expr_size(expr->bin_expr1, bits, list, &tmp);
-
-            if (result)
-                result = compute_conv_expr_size(expr->bin_expr1, bits, list, size);
-
-            if (tmp > *size) *size = tmp;
-
-            break;
-
-        default:
-            result = false;
-            break;
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = première expression à encapsuler.                     *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                data = éventuelle donnée à transmettre à chaque visite.      *
-*                                                                             *
-*  Description : Visite une expression en traitant en premier ses composantes.*
-*                                                                             *
-*  Retour      : Bilan des traitements effectués.                             *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool visit_conv_expr(conv_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    switch (expr->type)
-    {
-        case CET_UNARY:
-            result = visit_conv_expr(expr->un_expr, visit, fd, bits, list, data);
-            break;
-
-        case CET_BINARY:
-            result = visit_conv_expr(expr->bin_expr1, visit, fd, bits, list, data);
-            result = visit_conv_expr(expr->bin_expr2, visit, fd, bits, list, data);
-            break;
-
-        default:
-            result = true;
-            break;
-
-    }
-
-    result &= visit(expr, fd, bits, list, data);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : bits  = gestionnaire des bits d'encodage.                    *
-*                list  = liste de l'ensemble des fonctions de conversion.     *
-*                name  = déssignation de la variable recherchée.              *
-*                field = éventuel élement brut de décodage.                   *
-*                func  = éventuelle fonction de conversion pour intermédiaire.*
-*                                                                             *
-*  Description : Retrouve si elle existe une variable manipulée.              *
-*                                                                             *
-*  Retour      : Bilan des recherches : trouvaille ou non ?                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func)
-{
-    bool result;                            /* Bilan à retourner           */
-    raw_bitfield *cached_field;             /* Champ, version cachée       */
-    conv_func *cached_func;                 /* Fonction, version cachée    */
-
-    cached_field = find_named_field_in_bits(bits, name);
-    result = (cached_field != NULL);
-
-    if (!result)
-    {
-        cached_func = find_named_conv_in_list(list, name);
-        result = (cached_func != NULL);
-    }
-    else
-        cached_func = NULL;
-
-    if (field != NULL) *field = cached_field;
-    if (func != NULL) *func = cached_func;
-
-    if (!result)
-        fprintf(stderr, "Variable '%s' not found!\n", name);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = première expression à encapsuler.                     *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                                                                             *
-*  Description : S'assure du marquage des expressions pre-requises.           *
-*                                                                             *
-*  Retour      : Bilan des traitements effectués.                             *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool ensure_conv_expr_content_fully_marked(conv_expr_t *expr, const coding_bits *bits, const conv_list *list)
-{
-    bool mark_sub_expr(conv_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused)
-    {
-        bool result;                        /* Bilan à retourner           */
-        size_t i;                           /* Boucle de parcours          */
-
-        bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name)
-        {
-            bool found;                     /* Bilan d'opération à renvoyer*/
-            raw_bitfield *field;            /* Eventuel champ brut associé */
-            conv_func *func;                /* Eventuelle fonction liée    */
-
-            found = find_var_by_name(bts, lst, name, &field, &func);
-
-            if (found)
-            {
-                if (field != NULL)
-                    mark_raw_bitfield_as_used(field);
-                else /*if (func != NULL) */
-                    mark_conv_func(func, bts, lst);
-
-                printf(" VAR '%s' found (bf=%d  fc=%d)\n", name, !!field, !!func);
-
-
-            }
-            else printf(" VAR '%s' not found...\n", name);
-
-            return found;
-
-        }
-
-        /* Il est uniquement nécessaire de s'attacher aux références */
-        switch (sub->type)
-        {
-            case CET_NAME:
-                result = mark_by_name(bits, lst, sub->name);
-                break;
-
-            case CET_COMPOSED:
-                result = true;
-                for (i = 0; i < sub->comp_count && result; i++)
-                    if (!isdigit(sub->comp_items[i][0]))
-                        result = mark_by_name(bits, lst, sub->comp_items[i]);
-                break;
-
-            default:
-                result = true;
-                break;
-
-        }
-
-        return result;
-
-    }
-
-    return visit_conv_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = première expression à encapsuler.                     *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                arch = architecture visée par l'opération globale.           *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                wide = taille des mots décodés.                              *
-*                                                                             *
-*  Description : S'assure de la déclaration des expressions pre-requises.     *
-*                                                                             *
-*  Retour      : Bilan des traitements effectués.                             *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool ensure_conv_expr_content_fully_declared(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
-{
-    bool declare_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide)
-    {
-        bool result;                        /* Bilan à retourner           */
-        size_t i;                           /* Boucle de parcours          */
-
-        /* Si l'expression a déjà été définie lors d'un précédent besoin... */
-        printf("  sub declared ? %d  --  type = %d\n", sub->declared, sub->type);
-        if (sub->declared) return true;
-
-        bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name)
-        {
-            bool found;                     /* Bilan d'opération à renvoyer*/
-            conv_func *func;                /* Eventuelle fonction liée    */
-
-            found = find_var_by_name(bts, lst, name, NULL, &func);
-
-            if (found && func != NULL)
-            {
-                if (func->is_expr)
-                    dprintf(_f, "\t\tuint%u_t val_%s;\n", _wide, name);
-                else
-                    dprintf(_f, "\t\tGArchOperand *val_%s;\n", name);
-
-                printf("========= DECLARE for '%s'\n", name);
-                found = declare_conv_func(func, _f, _bts, _lst, _wide);
-                printf("========= END DECLARE for '%s'\n", name);
-            }
-
-            return found;
-
-        }
-
-        /* Il est uniquement nécessaire de s'attacher aux références */
-        switch (sub->type)
-        {
-            case CET_NAME:
-                result = declare_by_name(f, bits, lst, *wide, sub->name);
-                break;
-
-            case CET_COMPOSED:
-                result = true;
-                for (i = 0; i < sub->comp_count && result; i++)
-                    if (!isdigit(sub->comp_items[i][0]))
-                        printf("... trying to declare... '%s'\n", sub->comp_items[i]);
-                for (i = 0; i < sub->comp_count && result; i++)
-                    if (!isdigit(sub->comp_items[i][0]))
-                        result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]);
-                break;
-
-            default:
-                result = true;
-                break;
-
-        }
-
-        sub->declared = result;
-
-        return result;
-
-    }
-
-    return visit_conv_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = première expression à encapsuler.                     *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                arch = architecture visée par l'opération globale.           *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                pp   = pré-processeur pour les échanges de chaînes.          *
-*                                                                             *
-*  Description : S'assure de la définition des expressions pre-requises.      *
-*                                                                             *
-*  Retour      : Bilan des traitements effectués.                             *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool ensure_conv_expr_content_fully_defined(conv_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
-{
-    typedef struct _def_info
-    {
-        const char *arch;
-        const pre_processor *pp;
-
-    } def_info;
-
-    def_info info;                          /* Transmissions au visiteur   */
-
-    bool define_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info)
-    {
-        bool result;                        /* Bilan à retourner           */
-        size_t i;                           /* Boucle de parcours          */
-
-        /* Si l'expression a déjà été définie lors d'un précédent besoin... */
-        if (sub->defined) return true;
-
-        bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name)
-        {
-            bool found;                     /* Bilan d'opération à renvoyer*/
-            conv_func *func;                /* Eventuelle fonction liée    */
-
-            found = find_var_by_name(bts, lst, name, NULL, &func);
-
-            if (found && func != NULL)
-                found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp);
-
-            return found;
-
-        }
-
-        /* Il est uniquement nécessaire de s'attacher aux références */
-        switch (sub->type)
-        {
-            case CET_NAME:
-                result = define_by_name(f, bits, lst, info, sub->name);
-                break;
-
-            case CET_COMPOSED:
-                result = true;
-                for (i = 0; i < sub->comp_count && result; i++)
-                    if (!isdigit(sub->comp_items[i][0]))
-                        result = define_by_name(f, bits, lst, info, sub->comp_items[i]);
-                break;
-
-            default:
-                result = true;
-                break;
-
-        }
-
-        sub->defined = result;
-
-        return result;
-
-    }
-
-    info.arch = arch;
-    info.pp = pp;
-
-    return visit_conv_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = première expression à encapsuler.                     *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                                                                             *
-*  Description : Définit une expression utilisée dans une conversion.         *
-*                                                                             *
-*  Retour      : Bilan des traitements effectués.                             *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool define_conv_expr(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list)
-{
-    bool result;                            /* Bilan à retourner           */
-    raw_bitfield *field;                    /* Eventuel champ brut associé */
-    conv_func *func;                        /* Eventuelle fonction liée    */
-    unsigned int max_size;                  /* Quantité de bits totale     */
-    size_t i;                               /* Boucle de parcours          */
-    const char *cname;                      /* Raccourci de confort        */
-    unsigned int used_size;                 /* Quantité de bits utilisée   */
-
-    result = true;
-
-    switch (expr->type)
-    {
-        case CET_NAME:
-
-            if (!find_var_by_name(bits, list, expr->name, &field, &func))
-                result = false;
-
-            else
-            {
-                if (field != NULL)
-                    dprintf(fd, "raw_%s", expr->name);
-                else
-                    dprintf(fd, "val_%s", expr->name);
-            }
-
-            break;
-
-        case CET_NUMBER:
-            dprintf(fd, "%lu", expr->number);
-            break;
-
-        case CET_COMPOSED:
-
-            result = compute_conv_expr_size(expr, bits, list, &max_size);
-
-            printf("MAX SIZE :: %u\n", max_size);
-
-            for (i = 0; i < expr->comp_count && result; i++)
-            {
-                cname = expr->comp_items[i];
-
-                if (i > 0)
-                    dprintf(fd, " | ");
-
-                /* Constante binaire ? */
-                if (isdigit(cname[0]))
-                {
-                    max_size -= strlen(cname);
-
-                    if (max_size == 0)
-                        dprintf(fd, "b%s", cname);
-                    else
-                        dprintf(fd, "b%s << %u", cname, max_size);
-
-                }
-
-                /* Ou variable définie ? */
-                else
-                {
-                    result = find_var_by_name(bits, list, cname, &field, &func);
-
-                    if (result)
-                    {
-                        if (field != NULL)
-                            used_size = get_raw_bitfield_length(field);
-                        else
-                            /*result = */compute_conv_func_size(func, bits, list, &used_size);
-
-                        max_size -= used_size;
-
-                        if (field != NULL)
-                        {
-                            if (max_size == 0)
-                                dprintf(fd, "raw_%s", cname);
-                            else
-                                dprintf(fd, "raw_%s << %u", cname, max_size);
-                        }
-                        else
-                        {
-                            if (max_size == 0)
-                                dprintf(fd, "val_%s", cname);
-                            else
-                                dprintf(fd, "val_%s << %u", cname, max_size);
-                        }
-
-                    }
-
-                }
-
-            }
-
-            break;
-
-        case CET_UNARY:
-
-            switch (expr->un_op)
-            {
-                case CUO_NOT:
-                    dprintf(fd, "!");
-                    break;
-                default:
-                    result = false;
-                    break;
-            }
-
-            result &= define_conv_expr(expr->un_expr, fd, bits, list);
-
-            break;
-
-        case CET_BINARY:
-
-            dprintf(fd, "(");
-
-            result = define_conv_expr(expr->bin_expr1, fd, bits, list);
-
-            switch (expr->bin_op)
-            {
-                case CBO_EOR:
-                    dprintf(fd, " ^ ");
-                    break;
-                default:
-                    result = false;
-                    break;
-            }
-
-            result &= define_conv_expr(expr->bin_expr2, fd, bits, list);
-
-            dprintf(fd, ")");
-
-            break;
-
-        default:
-            result = false;
-            break;
-
-    }
-
-    return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                          LISTES D'ARGUMENTS DE CONVERSION                          */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr = expression initial pour constituer une liste.         *
-*                                                                             *
-*  Description : Crée une liste d'arguments de conversion.                    *
-*                                                                             *
-*  Retour      : Nouvelle structure mise en place.                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_arg_list_t *build_conv_arg_list(conv_expr_t *expr)
-{
-    conv_arg_list_t *result;                /* Structure à retourner       */
-
-    result = (conv_arg_list_t *)calloc(1, sizeof(conv_arg_list_t));
-
-    result->items = (conv_expr_t **)calloc(1, sizeof(conv_expr_t *));
-    result->count = 1;
-
-    result->items[0] = expr;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : list = liste d'expressions à supprimer de la mémoire.        *
-*                                                                             *
-*  Description : Libère la mémoire occupée par une liste d'expressions.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void delete_conv_arg_list(conv_arg_list_t *list)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < list->count; i++)
-        delete_conv_expr(list->items[i]);
-
-    if (list->items != NULL)
-        free(list->items);
-
-    free(list);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : list = liste d'expressions à supprimer de la mémoire. [OUT]  *
-*                expr = expression à ajouter à la liste courante.             *
-*                                                                             *
-*  Description : Ajoute un élément à une liste d'arguments de conversion.     *
-*                                                                             *
-*  Retour      : Structure en place mise à jour.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *list, conv_expr_t *expr)
-{
-    list->items = (conv_expr_t **)realloc(list->items, ++list->count * sizeof(conv_expr_t *));
-
-    list->items[list->count - 1] = expr;
-
-    return list;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                                                                             *
-*  Description : S'assure du marquage des expressions pre-requises.           *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *args, const coding_bits *bits, const conv_list *list)
-{
-    bool result;                            /* Bilan à remonter            */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = true;
-
-    for (i = 0; i < args->count && result; i++)
-        result = ensure_conv_expr_content_fully_marked(args->items[i], bits, list);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                wide = taille des mots décodés.                              *
-*                                                                             *
-*  Description : S'assure de la déclaration des expressions pre-requises.     *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+/* Fonction de conversion */
+struct _conv_func
 {
-    bool result;                            /* Bilan à remonter            */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = true;
-
-    for (i = 0; i < args->count && result; i++)
-        result = ensure_conv_expr_content_fully_declared(args->items[i], fd, bits, list, wide);
+    bool declared;                          /* Expression déjà déclarée ?  */
+    bool defined;                           /* Expression déjà définie ?   */
 
-    return result;
+    char *dest;                             /* Variable de destination     */
 
-}
+    bool is_expr;                           /* Choix du contenu réel       */
 
+    union
+    {
+        arg_expr_t *expr;                   /* Valeur expressive directe   */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                arch = architecture visée par l'opération globale.           *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                pp   = pré-processeur pour les échanges de chaînes.          *
-*                                                                             *
-*  Description : S'assure de la définition des expressions pre-requises.      *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+        struct
+        {
+            char *name;                     /* Fonction de conversion      */
+            arg_list_t *args;               /* Liste des arguments         */
 
-static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
-{
-    bool result;                            /* Bilan à remonter            */
-    size_t i;                               /* Boucle de parcours          */
+        };
 
-    result = true;
+    };
 
-    for (i = 0; i < args->count && result; i++)
-        result = ensure_conv_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp);
+};
 
-    return result;
 
-}
 
+/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : args = liste d'expressions à supprimer de la mémoire.        *
-*                fd   = descripteur d'un flux ouvert en écriture.             *
-*                bits = gestionnaire des bits d'encodage.                     *
-*                list = liste de l'ensemble des fonctions de conversion.      *
-*                                                                             *
-*  Description : Définit les variables associées à un appel de fonction.      *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list)
+/* Liste des fonctions de conversions présentes */
+struct _conv_list
 {
-    bool result;                            /* Bilan à remonter            */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = true;
-
-    for (i = 0; i < args->count && result; i++)
-    {
-        if (i > 0) dprintf(fd, ", ");
-        result = define_conv_expr(args->items[i], fd, bits, list);
-    }
-
-    return result;
+    conv_func **functions;                 /* Fonctions de conversion     */
+    size_t func_count;                     /* Nombre de ces fonctions     */
 
-}
+};
 
 
 
@@ -1206,7 +97,7 @@ static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bi
 *                                                                             *
 ******************************************************************************/
 
-conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr)
+conv_func *make_conv_from_expr(char *dest, arg_expr_t *expr)
 {
     conv_func *result;                      /* Conversion à retourner      */
 
@@ -1236,7 +127,7 @@ conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr)
 *                                                                             *
 ******************************************************************************/
 
-conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args)
+conv_func *make_conv_from_func(char *dest, char *func, arg_list_t *args)
 {
     conv_func *result;                      /* Conversion à retourner      */
 
@@ -1268,12 +159,12 @@ conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args)
 void delete_conv_func(conv_func *func)
 {
     if (func->is_expr)
-        delete_conv_expr(func->expr);
+        delete_arg_expr(func->expr);
 
     else
     {
         free(func->name);
-        delete_conv_arg_list(func->args);
+        delete_arg_list(func->args);
     }
 
     free(func);
@@ -1303,6 +194,25 @@ const char *get_conv_dest_name(const conv_func *func)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : func = fonction de conversion à consulter.                   *
+*                                                                             *
+*  Description : Indique la nature d'une conversion : fonction ou expression ?*
+*                                                                             *
+*  Retour      : Indication sur la constitution interne de la conversion.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool is_conv_func_expression(const conv_func *func)
+{
+    return func->is_expr;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = fonction de conversion à consulter.                   *
 *                bits = gestionnaire des bits d'encodage.                     *
 *                list = liste de l'ensemble des fonctions de conversion.      *
 *                size = taille déterminée avec précision. [OUT]               *
@@ -1315,14 +225,14 @@ const char *get_conv_dest_name(const conv_func *func)
 *                                                                             *
 ******************************************************************************/
 
-static bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size)
+bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size)
 {
     bool result;                            /* Bilan à retourner           */
 
     result = func->is_expr;
 
     if (result)
-        result = compute_conv_expr_size(func->expr, bits, list, size);
+        result = compute_arg_expr_size(func->expr, bits, list, size);
 
     return result;
 
@@ -1348,7 +258,7 @@ bool mark_conv_func(conv_func *func, const coding_bits *bits, const conv_list *l
     bool result;                            /* Bilan à remonter            */
 
     if (func->is_expr)
-        result = ensure_conv_expr_content_fully_marked(func->expr, bits, list);
+        result = ensure_arg_expr_content_fully_marked(func->expr, bits, list);
     else
         result = ensure_arg_list_content_fully_marked(func->args, bits, list);
 
@@ -1378,11 +288,11 @@ bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const c
     bool result;                            /* Bilan à remonter            */
 
     /* Si la fonction a déjà été définie lors d'un précédent besoin... */
-    printf("  func declared ? %d\n", func->declared);
     if (func->declared) return true;
 
     if (func->is_expr)
-        result = ensure_conv_expr_content_fully_declared(func->expr, fd, bits, list, wide);
+        result = ensure_arg_expr_content_fully_declared(func->expr, fd, bits, list, wide);
+
     else
         result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, wide);
 
@@ -1416,17 +326,12 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c
 {
     bool result;                            /* Bilan à remonter            */
     const char *callable;                   /* Fonction à appeler          */
-    regex_t preg;                           /* Expression régulière        */
-    int ret;                                /* Bilan d'une manipulation    */
-    regmatch_t pmatch[3];                   /* Correspondances de chaînes  */
-    size_t cmplen;                          /* Taille de comparaison       */
-    char *cast;                             /* Macro de transtypage        */
 
     /* Si la fonction a déjà été définie lors d'un précédent besoin... */
     if (func->defined) return true;
 
     if (func->is_expr)
-        result = ensure_conv_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp);
+        result = ensure_arg_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp);
     else
         result = ensure_arg_list_content_fully_defined(func->args, fd, arch, bits, list, pp);
 
@@ -1453,53 +358,7 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c
     {
         /* Si l'on doit manipuler une propriété d'instructon... */
         if (internal)
-        {
-            ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
-            if (ret != 0)
-            {
-                fprintf(stderr, "Internal error: bad regular expression.\n");
-                return false;
-            }
-
-            ret = regexec(&preg, callable, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);
-            if (ret == REG_NOMATCH)
-            {
-                fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callable);
-                result = false;
-                goto dcf_skip_internal;
-            }
-
-            /**
-             * La variable de résultat est de type 'GArchInstruction',
-             * donc toute fonction différente de g_arch_instruction_*() attend un transtypage...
-             */
-
-            cmplen = MAX(strlen(arch), pmatch[2].rm_eo - pmatch[2].rm_so);
-
-            if (strncmp("arch", &callable[pmatch[2].rm_so], cmplen) == 0)
-                dprintf(fd, "\t\tif (!%s(instr, ", callable);
-
-            else
-            {
-                cast = strndup(&callable[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
-
-                cast = make_string_upper(cast);
-
-                dprintf(fd, "\t\tif (!%s(%s(instr), ", callable, cast);
-
-                free(cast);
-
-            }
-
-            result &= define_arg_list(func->args, fd, bits, list);
-
-            dprintf(fd, "))\n");
-
- dcf_skip_internal:
-
-            regfree(&preg);
-
-        }
+            result = call_instr_func(callable, func->args, fd, bits, list, pp);
 
         /* Si on doit constituer un opérande à ajouter... */
         else
@@ -1523,7 +382,7 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c
         dprintf(fd, "\t\tval_%s = ", func->dest);
 
         if (func->is_expr)
-            result &= define_conv_expr(func->expr, fd, bits, list);
+            result &= define_arg_expr(func->expr, fd, bits, list);
 
         else
         {
diff --git a/tools/d2c/conv.h b/tools/d2c/conv.h
index acf007b..85c7578 100644
--- a/tools/d2c/conv.h
+++ b/tools/d2c/conv.h
@@ -25,88 +25,12 @@
 #define _TOOLS_CONV_H
 
 
-#include "bits.h"
-#include "pproc.h"
-
-
-
-
-/* Liste des fonctions de conversions présentes */
-typedef struct _conv_list conv_list;
-
-
-
-
-
-
-
-/* Types d'opérations unaires */
-typedef enum _ConvUnaryOperation
-{
-    CUO_NOT,                                /* NOT (booléen)               */
-
-    CUO_COUNT
-
-} ConvUnaryOperation;
-
-
-
-/* Types d'opérations binaires */
-typedef enum _ConvBinaryOperation
-{
-    CBO_EOR,                                /* Ou exclusif (booléen)       */
-
-    CBO_COUNT
-
-} ConvBinaryOperation;
-
-
-/* Représentation d'une expression de conversion */
-typedef struct _conv_expr_t conv_expr_t;
-
-
-
-/* Référence une variable en tant qu'expression de conversion. */
-conv_expr_t *build_conv_expr_from_name(char *);
+#include <stdbool.h>
 
-/* Conserve une valeur en tant qu'expression de conversion. */
-conv_expr_t *build_conv_expr_from_number(unsigned long );
-
-/* Construit une base d'expression de conversion composée. */
-conv_expr_t *build_composed_conv_expr(char *, char *);
-
-/* Etend une base d'expression de conversion composée. */
-conv_expr_t *extend_composed_conv_expr(conv_expr_t *, char *);
-
-/* Traduit une opération unaire sur expression de conversion. */
-conv_expr_t *build_unary_conv_expr(conv_expr_t *, ConvUnaryOperation);
-
-/* Traduit une opération binaire sur expression de conversion. */
-conv_expr_t *build_binary_conv_expr(conv_expr_t *, conv_expr_t *, ConvBinaryOperation);
-
-
-
-
-
-
-
-
-/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */
-
-
-/* Liste d'expressions utilisées en arguments de conversion */
-typedef struct _conv_arg_list_t conv_arg_list_t;
-
-
-/* Crée une liste d'arguments de conversion. */
-conv_arg_list_t *build_conv_arg_list(conv_expr_t *);
-
-/* Libère la mémoire occupée par une liste d'expressions. */
-void delete_conv_arg_list(conv_arg_list_t *);
-
-/* Ajoute un élément à une liste d'arguments de conversion. */
-conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *, conv_expr_t *);
 
+#include "args.h"
+#include "bits.h"
+#include "pproc.h"
 
 
 
@@ -118,10 +42,10 @@ typedef struct _conv_func conv_func;
 
 
 /* Définit une conversion à partir d'une simple expression. */
-conv_func *make_conv_from_expr(char *, conv_expr_t *);
+conv_func *make_conv_from_expr(char *, arg_expr_t *);
 
 /* Définit une conversion à partir d'une function à appeler. */
-conv_func *make_conv_from_func(char *, char *, conv_arg_list_t *);
+conv_func *make_conv_from_func(char *, char *, arg_list_t *);
 
 /* Libère de la mémoire une conversion enregistrée. */
 void delete_conv_func(conv_func *);
@@ -129,6 +53,12 @@ void delete_conv_func(conv_func *);
 /* Indique la variable de destination d'une conversion. */
 const char *get_conv_dest_name(const conv_func *);
 
+/* Indique la nature d'une conversion : fonction ou expression ? */
+bool is_conv_func_expression(const conv_func *);
+
+/* Détermine la taille en bits du résultat d'une fonction. */
+bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *);
+
 /* Marque les champs utilisés par une fonction de conversion. */
 bool mark_conv_func(conv_func *, const coding_bits *, const conv_list *);
 
@@ -143,6 +73,10 @@ bool define_conv_func(conv_func *, bool, bool, int, const char *, const coding_b
 /* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
 
 
+/* Liste des fonctions de conversions présentes */
+typedef struct _conv_list conv_list;
+
+
 /* Crée un nouvelle liste vierge de fonctions de conversion. */
 conv_list *create_conv_list(void);
 
diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y
index 12eff11..9e1e034 100644
--- a/tools/d2c/d2c_gram.y
+++ b/tools/d2c/d2c_gram.y
@@ -33,6 +33,7 @@ static void show_usage(const char *);
 #include "coder.h"
 
 #include "conv.h"
+#include "helpers.h"
 
 struct action_tmp
 {
@@ -95,13 +96,13 @@ struct action_tmp
         register_hook_function(__hooks, t, f);              \
     })
 
-#define add_conditional_rule_to_coder(c, e, a, d)           \
+#define add_conditional_rule_to_coder(c, e, a)              \
     ({                                                      \
         encoding_spec *__spec;                              \
         decoding_rules *__rules;                            \
         __spec = get_current_encoding_spec(c);              \
         __rules = get_rules_in_encoding_spec(__spec);       \
-        register_conditional_rule(__rules, e, a, d);        \
+        register_conditional_rule(__rules, e, a);           \
     })
 
 }
@@ -115,15 +116,15 @@ struct action_tmp
     int integer;
 
     conv_func *subst;                       /* Fonction de conversion      */
-    conv_arg_list_t *conv_list;             /* Liste d'arguments de conv.  */
+    arg_list_t *args;                       /* Liste d'arguments           */
 
-    conv_expr_t *conv;                      /* Expression de conversion    */
+    arg_expr_t *arg;                        /* Argument multi-usages       */
     ConvUnaryOperation un_op;               /* Opération unaire            */
     ConvBinaryOperation bin_op;             /* Opération bianire           */
 
 
     cond_expr *expr;                        /* Expression de déclenchement */
-    struct action_tmp tmpa;                 /* Transfert temporaire        */
+    rule_action raction;                    /* Action et éléments associés */
 
 }
 
@@ -146,7 +147,7 @@ struct action_tmp
 
 %token HOOKS
 
-%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE UNPREDICTABLE
+%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE CALL UNPREDICTABLE
 
 
 %type <string> COPYRIGHT INS_NAME
@@ -160,17 +161,17 @@ struct action_tmp
 
 %type <string> OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
 
-
 %type <subst> substitution
-%type <conv_list> conv_arg_list
-%type <conv> conv_expr conv_arg_composed
-%type <un_op> conv_expr_un_op
-%type <bin_op> conv_expr_bin_op
-%type <string> conv_arg_field
+
+%type <args> arg_list
+%type <arg> arg_expr arg_composed
+%type <un_op> arg_expr_un_op
+%type <bin_op> arg_expr_bin_op
+%type <string> arg_field
 
 %type <expr> rule_cond
 %type <string> BINVAL IMMVAL
-%type <tmpa> action
+%type <raction> action
 
 
 %%
@@ -231,28 +232,29 @@ conversions : CONV substitutions
 substitutions : /* empty */
               | substitutions substitution { register_conversion_in_coder(coder, $2); }
 
-substitution : NAME EQ conv_expr                { $$ = make_conv_from_expr($1, $3); }
-             | NAME EQ NAME OP conv_arg_list CP { $$ = make_conv_from_func($1, $3, $5); }
+substitution : NAME EQ arg_expr            { $$ = make_conv_from_expr($1, $3); }
+             | NAME EQ NAME OP arg_list CP { $$ = make_conv_from_func($1, $3, $5); }
+
 
-conv_arg_list : conv_expr                     { $$ = build_conv_arg_list($1); }
-              | conv_arg_list COMMA conv_expr { $$ = extend_conv_arg_list($1, $3); printf("extend\n"); }
+arg_list : arg_expr                { $$ = build_arg_list($1); }
+         | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); }
 
-conv_expr : NAME                                       { $$ = build_conv_expr_from_name($1); }
-          | NUMBER                                     { $$ = build_conv_expr_from_number($1); }
-          | conv_arg_composed                          { $$ = $1; }
-          | OP conv_expr CP                            { $$ = $2; }
-          | conv_expr_un_op conv_expr                  { $$ = build_unary_conv_expr($2, $1); }
-          | OP conv_expr conv_expr_bin_op conv_expr CP { $$ = build_binary_conv_expr($2, $4, $3); }
+arg_expr : NAME                                     { $$ = build_arg_expr_from_name($1); }
+          | NUMBER                                  { $$ = build_arg_expr_from_number($1); }
+          | arg_composed                            { $$ = $1; }
+          | OP arg_expr CP                          { $$ = $2; }
+          | arg_expr_un_op arg_expr                 { $$ = build_unary_arg_expr($2, $1); }
+          | OP arg_expr arg_expr_bin_op arg_expr CP { $$ = build_binary_arg_expr($2, $4, $3); }
 
-conv_expr_un_op : NOT { $$ = CUO_NOT; }
+arg_expr_un_op : NOT { $$ = CUO_NOT; }
 
-conv_expr_bin_op : EOR { $$ = CBO_EOR; }
+arg_expr_bin_op : EOR { $$ = CBO_EOR; }
 
-conv_arg_composed : conv_arg_field COLON conv_arg_field    { $$ = build_composed_conv_expr($1, $3); }
-                  | conv_arg_composed COLON conv_arg_field { $$ = extend_composed_conv_expr($1, $3); }
+arg_composed : arg_field COLON arg_field    { $$ = build_composed_arg_expr($1, $3); }
+             | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); }
 
-conv_arg_field : NAME   { $$ = $1; printf(" composed::name '%s'\n", $1); }
-               | BINVAL { $$ = $1; printf(" composed::bin '%s'\n", $1); }
+arg_field : NAME   { $$ = $1; }
+          | BINVAL { $$ = $1; }
 
 
 hooks : HOOKS hookings
@@ -268,16 +270,17 @@ rules : RULES rules_list
 rules_list : /* empty */
            | rules_list rule
 
-rule : IF EXPR_START rule_cond EXPR_END THEN action
-                                { add_conditional_rule_to_coder(coder, $3, $6.action, $6.details); }
+rule : IF EXPR_START rule_cond EXPR_END THEN action { add_conditional_rule_to_coder(coder, $3, &$6); }
+     | action                                       { add_conditional_rule_to_coder(coder, NULL, &$1); }
 
 rule_cond : NAME EQUAL BINVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); }
           | NAME EQUAL IMMVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); }
           | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END
                                 { $$ = build_composed_cond_expression($2, COT_AND, $6); }
 
-action : SEE INS_DETAILS { $$.action = CAT_SEE; $$.details = $2; }
-       | UNPREDICTABLE   { $$.action = CAT_UNPREDICTABLE; $$.details = NULL; }
+action : SEE INS_DETAILS          { $$.type = CAT_SEE; $$.details = make_callable($2, false); }
+       | UNPREDICTABLE            { $$.type = CAT_UNPREDICTABLE; }
+       | CALL NAME OP arg_list CP { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; }
 
 
 %%
diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l
index 8f54c8d..9689b59 100644
--- a/tools/d2c/d2c_tok.l
+++ b/tools/d2c/d2c_tok.l
@@ -19,7 +19,9 @@ void free_flex_memory(void) ;
 %option noyywrap
 %option nounput
 %option noinput
-%option   yylineno
+%option yylineno
+%option stack
+%option noyy_top_state
 
 
 %x comments
@@ -33,9 +35,11 @@ void free_flex_memory(void) ;
 
 %x conv_begin conv_content conv_arg conv_arg_binval
 
+%x arg arg_binval
+
 %x hooks_begin hooks_content
 
-%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see
+%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see rules_action_call
 
 
 %%
@@ -127,6 +131,10 @@ void free_flex_memory(void) ;
                                     }
 <conv_content>"="                   { return EQ; }
 <conv_content>"("                   { BEGIN(conv_arg); return OP; }
+
+
+
+
 <conv_arg>[A-Za-z][A-Za-z0-9_]*      {
                                       if (strcmp(yytext, "NOT") == 0) return NOT;
                                       else if (strcmp(yytext, "EOR") == 0) return EOR;
@@ -147,6 +155,33 @@ void free_flex_memory(void) ;
 
 
 
+
+
+
+
+
+
+<arg>[A-Za-z][A-Za-z0-9_]*     {
+                                   if (strcmp(yytext, "NOT") == 0) return NOT;
+                                   else if (strcmp(yytext, "EOR") == 0) return EOR;
+                                   else
+                                   {
+                                       d2c_lval.string = strdup(yytext);
+                                       return NAME;
+                                   }
+                               }
+<arg>[0-9][0-9]*               { d2c_lval.integer = atoi(yytext); return NUMBER; }
+<arg>"'"                       { BEGIN(arg_binval); }
+<arg_binval>[01][01]*          { d2c_lval.string = strdup(yytext); return BINVAL; }
+<arg_binval>"'"                { BEGIN(arg); }
+<arg>","                       { return COMMA; }
+<arg>":"                       { return COLON; }
+<arg>[ ]+                      { }
+<arg>")"                       { yy_pop_state(); return CP; }
+
+
+
+
 <encoding_content>"@hooks"          { BEGIN(hooks_begin); return HOOKS; }
 <hooks_begin>[ ]+                   { }
 <hooks_begin>"{"                    { BEGIN(hooks_content); }
@@ -165,6 +200,10 @@ void free_flex_memory(void) ;
 <rules_content>[ \t\n]+             { }
 <rules_content>"}"                  { BEGIN(encoding_content); }
 
+<rules_content>"see "               { BEGIN(rules_action_see); return SEE; }
+<rules_content>"unpredictable"      { return UNPREDICTABLE; }
+<rules_content>"call"               { BEGIN(rules_action_call); return CALL; }
+
 <rules_content>"if"                 { BEGIN(rules_cond); return IF; }
 <rules_cond>[ ]+                    { }
 <rules_cond>"("                     { return EXPR_START; }
@@ -179,10 +218,18 @@ void free_flex_memory(void) ;
 
 <rules_cond>";"                     { BEGIN(rules_action); return THEN; }
 <rules_action>[ ]+                  { }
+
 <rules_action>"see "                { BEGIN(rules_action_see); return SEE; }
 <rules_action_see>[^\n]*            { d2c_lval.cstring = yytext; BEGIN(rules_content); return INS_DETAILS; }
+
 <rules_action>"unpredictable"       { BEGIN(rules_content); return UNPREDICTABLE; }
 
+<rules_action>"call"                    { BEGIN(rules_action_call); return CALL; }
+<rules_action_call>[\t ]+               { }
+<rules_action_call>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; }
+<rules_action_call>"("                  { yy_push_state(arg); return OP; }
+<rules_action_call>[\n]                 { BEGIN(rules_content); }
+
 
 %%
 
diff --git a/tools/d2c/qckcall.c b/tools/d2c/qckcall.c
new file mode 100644
index 0000000..ce9a0b2
--- /dev/null
+++ b/tools/d2c/qckcall.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * qckcall.c - appel rapide et facilité à une fonction C de Chrysalide
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  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 "qckcall.h"
+
+
+#include <malloc.h>
+#include <regex.h>
+#include <string.h>
+#include <sys/param.h>
+
+
+#include "helpers.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : callee = fonction appelée à nomer.                           *
+*                args   = précise si la conversion est la dernière.           *
+*                fd     = descripteur d'un flux ouvert en écriture.           *
+*                bits   = gestionnaire des bits d'encodage.                   *
+*                list   = liste de l'ensemble des fonctions de conversion.    *
+*                pp     = pré-processeur pour les échanges de chaînes.        *
+*                                                                             *
+*  Description : Réalise un appel à une fonction liée à une instruction.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+    bool result;                            /* Bilan à remonter            */
+    regex_t preg;                           /* Expression régulière        */
+    int ret;                                /* Bilan d'une manipulation    */
+    regmatch_t pmatch[3];                   /* Correspondances de chaînes  */
+    size_t cmplen;                          /* Taille de comparaison       */
+    char *cast;                             /* Macro de transtypage        */
+
+    ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
+    if (ret != 0)
+    {
+        fprintf(stderr, "Internal error: bad regular expression.\n");
+        return false;
+    }
+
+    ret = regexec(&preg, callee, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);
+    if (ret == REG_NOMATCH)
+    {
+        fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callee);
+        result = false;
+        goto cif_exit;
+    }
+
+    /**
+     * La variable de résultat est de type 'GArchInstruction',
+     * donc toute fonction différente de g_arch_instruction_*() attend un transtypage...
+     */
+
+    cmplen = MAX(strlen("arch"), pmatch[2].rm_eo - pmatch[2].rm_so);
+
+    if (strncmp("arch", &callee[pmatch[2].rm_so], cmplen) == 0)
+        dprintf(fd, "\t\tif (!%s(instr, ", callee);
+
+    else
+    {
+        cast = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+
+        cast = make_string_upper(cast);
+
+        dprintf(fd, "\t\tif (!%s(%s(instr), ", callee, cast);
+
+        free(cast);
+
+    }
+
+    result = define_arg_list(args, fd, bits, list);
+
+    dprintf(fd, "))\n");
+
+ cif_exit:
+
+    regfree(&preg);
+
+    return result;
+
+}
diff --git a/tools/d2c/qckcall.h b/tools/d2c/qckcall.h
new file mode 100644
index 0000000..59d4adc
--- /dev/null
+++ b/tools/d2c/qckcall.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * qckcall.h - prototypes pour un appel rapide et facilité à une fonction C de Chrysalide
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  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 _TOOLS_QCKCALL_H
+#define _TOOLS_QCKCALL_H
+
+
+#include <stdbool.h>
+
+
+
+#include "args.h"
+#include "conv.h"
+#include "bits.h"
+#include "pproc.h"
+
+
+
+/* Réalise un appel à une fonction liée à une instruction. */
+bool call_instr_func(const char *, const arg_list_t *, int, const coding_bits *, const conv_list *, const pre_processor *);
+
+
+
+#endif  /* _TOOLS_QCKCALL_H */
diff --git a/tools/d2c/rules.c b/tools/d2c/rules.c
index 73ec965..6f2e075 100644
--- a/tools/d2c/rules.c
+++ b/tools/d2c/rules.c
@@ -30,6 +30,7 @@
 
 
 #include "helpers.h"
+#include "qckcall.h"
 
 
 
@@ -79,8 +80,7 @@ static bool write_cond_expr(const cond_expr *, int, const coding_bits *);
 typedef struct _extra_rule
 {
     cond_expr *expr;                        /* Expression de déclenchement */
-    CondActionType action;                  /* Conséquence d'une validation*/
-    char *details;                          /* Eventuel complément d'info. */
+    rule_action action;                     /* Conséquence d'une validation*/
 
 } extra_rule;
 
@@ -320,12 +320,31 @@ decoding_rules *create_decoding_rules(void)
 void delete_decoding_rules(decoding_rules *rules)
 {
     size_t i;                               /* Boucle de parcours          */
+    extra_rule *rule;                       /* Règle à traiter             */
 
     for (i = 0; i < rules->extra_count; i++)
     {
-        delete_cond_expr(rules->extra[i].expr);
-        if (rules->extra[i].details)
-            free(rules->extra[i].details);
+        rule = &rules->extra[i];
+
+        if (rule->expr != NULL)
+            delete_cond_expr(rule->expr);
+
+        switch (rule->action.type)
+        {
+            case CAT_SEE:
+                free(rule->action.details);
+                break;
+
+            case CAT_UNPREDICTABLE:
+                break;
+
+            case CAT_CALL:
+                free(rule->action.callee);
+                delete_arg_list(rule->action.args);
+                break;
+
+        }
+
     }
 
     if (rules->extra != NULL)
@@ -341,7 +360,6 @@ void delete_decoding_rules(decoding_rules *rules)
 *  Paramètres  : rules   = ensemble de règles à compléter.                    *
 *                expr    = représentation d'expression à conserver.           *
 *                action  = conséquence associée à la règle.                   *
-*                details = éventuel complément d'informations.                *
 *                                                                             *
 *  Description : Ajoute une règle complète à la définition d'un codage.       *
 *                                                                             *
@@ -351,7 +369,7 @@ void delete_decoding_rules(decoding_rules *rules)
 *                                                                             *
 ******************************************************************************/
 
-void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActionType action, const char *details)
+void register_conditional_rule(decoding_rules *rules, cond_expr *expr, const rule_action *action)
 {
     extra_rule *rule;                       /* Nouvelle prise en compte    */
 
@@ -360,8 +378,7 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio
     rule = &rules->extra[rules->extra_count - 1];
 
     rule->expr = expr;
-    rule->action = action;
-    rule->details = (details != NULL ? make_callable(details, false) : NULL);
+    rule->action = *action;
 
 }
 
@@ -369,10 +386,13 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : rules   = ensemble de règles à consulter.                    *
+*                filter  = filtre sur les règles à effectivement imprimer.    *
 *                fd      = descripteur d'un flux ouvert en écriture.          *
 *                arch    = architecture visée par l'opération.                *
 *                subarch = sous-catégorie de cette même architecture.         *
 *                bits    = gestionnaire des bits d'encodage.                  *
+*                list    = liste de l'ensemble des fonctions de conversion.   *
+*                pp      = pré-processeur pour les échanges de chaînes.       *
 *                exit    = exprime le besoin d'une voie de sortie. [OUT]      *
 *                                                                             *
 *  Description : Traduit en code les éventuelles règles présentes.            *
@@ -383,40 +403,39 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio
 *                                                                             *
 ******************************************************************************/
 
-bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const char *subarch, const coding_bits *bits, bool *exit)
+bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd, const char *arch, const char *subarch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit)
 {
     bool result;                            /* Bilan à remonter            */
     const extra_rule *rule;                 /* Règle en cours d'écriture   */
     size_t i;                               /* Boucle de parcours          */
+    const char *callable;                   /* Fonction à appeler          */
 
     result = true;
 
-    *exit = false;
-
     for (i = 0; i < rules->extra_count; i++)
     {
         rule = &rules->extra[i];
 
-        dprintf(fd, "\t\tif ");
+        if (rule->action.type != filter)
+            continue;
 
-        result = write_cond_expr(rule->expr, fd, bits);
-        if (!result) break;
+        if (rule->expr != NULL)
+        {
+            dprintf(fd, "\t\tif ");
 
-        dprintf(fd, "\n");
-        dprintf(fd, "\t\t{\n");
+            result = write_cond_expr(rule->expr, fd, bits);
+            if (!result) break;
 
-        switch (rule->action)
+            dprintf(fd, "\n");
+            dprintf(fd, "\t\t{\n");
+
+        }
+
+        switch (rule->action.type)
         {
             case CAT_SEE:
 
-                if (rule->details == NULL)
-                {
-                    fprintf(stderr, "Error: directive 'see' must provide additional details.\n");
-                    result = false;
-                    goto wcsr_exit;
-                }
-
-                dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->details);
+                dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->action.details);
 
                 /* TODO : adapter les paramètres d'appel selon le 'coder' */
                 dprintf(fd, "(_raw);\n");
@@ -429,16 +448,35 @@ bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const
             case CAT_UNPREDICTABLE:
                 break;
 
+            case CAT_CALL:
+
+                callable = find_macro(pp, rule->action.callee);
+
+                if (callable == NULL)
+                    callable = rule->action.callee;
+
+                if (rule->expr != NULL)
+                    dprintf(fd, "\t");
+
+                result = call_instr_func(callable, rule->action.args, fd, bits, list, pp);
+
+                if (rule->expr != NULL)
+                    dprintf(fd, "\t");
+
+                dprintf(fd, "\t\t\tgoto quick_exit;\n");
+
+                *exit = true;
+                break;
+
         }
 
-        dprintf(fd, "\t\t}\n");
+        if (rule->expr != NULL)
+            dprintf(fd, "\t\t}\n");
 
         dprintf(fd, "\n");
 
     }
 
- wcsr_exit:
-
     return result;
 
 }
diff --git a/tools/d2c/rules.h b/tools/d2c/rules.h
index af2cac5..6344828 100644
--- a/tools/d2c/rules.h
+++ b/tools/d2c/rules.h
@@ -25,7 +25,10 @@
 #define _TOOLS_RULES_H
 
 
+#include "args.h"
 #include "bits.h"
+#include "conv.h"
+#include "pproc.h"
 
 
 
@@ -67,10 +70,33 @@ cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *);
 typedef enum _CondActionType
 {
     CAT_SEE,                                /* Renvoi vers une instruction */
-    CAT_UNPREDICTABLE                       /* Cas de figure improbable    */
+    CAT_UNPREDICTABLE,                      /* Cas de figure improbable    */
+    CAT_CALL                                /* Appel à une fonction C      */
 
 } CondActionType;
 
+/* Définition d'une action de règle */
+typedef struct _rule_action
+{
+    CondActionType type;                    /* Conséquence d'une validation*/
+
+    union
+    {
+        /* CAT_SEE */
+        char *details;                      /* Eventuel complément d'info. */
+
+        /* CAT_CALL */
+        struct
+        {
+            char *callee;                   /* Fonction appelée            */
+            arg_list_t *args;               /* Arguments à fournir         */
+
+        };
+
+    };
+
+} rule_action;
+
 /* Règles de décodage supplémentaires */
 typedef struct _decoding_rules decoding_rules;
 
@@ -82,10 +108,10 @@ decoding_rules *create_decoding_rules(void);
 void delete_decoding_rules(decoding_rules *);
 
 /* Ajoute une règle complète à la définition d'un codage. */
-void register_conditional_rule(decoding_rules *, cond_expr *, CondActionType, const char *);
+void register_conditional_rule(decoding_rules *, cond_expr *, const rule_action *);
 
 /* Traduit en code les éventuelles règles présentes. */
-bool write_decoding_rules(decoding_rules *, int, const char *, const char *, const coding_bits *, bool *);
+bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *);
 
 
 
diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c
index b56c6aa..9d4447d 100644
--- a/tools/d2c/spec.c
+++ b/tools/d2c/spec.c
@@ -304,7 +304,13 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
 
     /* Inclusion des éventuelles règles */
 
-    result &= write_decoding_rules(spec->rules, fd, arch, subarch, spec->bits, &exit);
+    exit = false;
+
+    result &= write_decoding_rules(spec->rules, CAT_SEE,
+                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
+
+    result &= write_decoding_rules(spec->rules, CAT_UNPREDICTABLE,
+                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
 
     /* Création de l'instruction en elle-même */
 
@@ -314,10 +320,13 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
 
     dprintf(fd, "\n");
 
-    /* Inscriptions des éventuelles fonctions à lier */
+    /* Inscriptions des éventuelles fonctions ou propriété à lier */
 
     result &= write_hook_functions(spec->hooks, fd);
 
+    result &= write_decoding_rules(spec->rules, CAT_CALL,
+                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
+
     /* Création des opérandes */
 
     result &= define_syntax_items(spec->syntax, fd, arch, spec->bits, spec->conversions, pp);
-- 
cgit v0.11.2-87-g4458