From ae8cf6257c8d929de1b7ee86e29fcb45ab4af91c Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 12 Nov 2010 22:13:21 +0000
Subject: Changed the display of the pseudo registers by using an index.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@192 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                    | 34 +++++++++++++++++++++++++++
 src/arch/dalvik/dop_aget.c   |  6 ++---
 src/arch/dalvik/dop_aput.c   |  6 ++---
 src/arch/dalvik/dop_arithm.c | 14 ++++-------
 src/arch/dalvik/dop_array.c  |  4 ++--
 src/arch/dalvik/dop_const.c  |  4 ++--
 src/arch/dalvik/dop_invoke.c |  6 ++---
 src/arch/dalvik/operand.c    | 30 +++++++++++++++++++++++-
 src/arch/dalvik/register.c   | 29 +++++++++++++++++++++++
 src/arch/dalvik/register.h   |  3 +++
 src/arch/operand-int.h       |  5 ++++
 src/arch/operand.c           | 27 ++++++++++++++++++++++
 src/arch/operand.h           |  3 +++
 src/decomp/context.c         | 55 ++++++++++++++++++++++++++++++++++++++++++++
 src/decomp/context.h         |  5 +++-
 src/decomp/expr/pseudo.c     | 30 +++++++++++++++++++++++-
 src/decomp/expr/pseudo.h     |  3 +++
 src/glibext/Makefile.am      |  1 +
 src/glibext/gnhash.c         | 52 +++++++++++++++++++++++++++++++++++++++++
 src/glibext/gnhash.h         | 37 +++++++++++++++++++++++++++++
 20 files changed, 329 insertions(+), 25 deletions(-)
 create mode 100644 src/glibext/gnhash.c
 create mode 100644 src/glibext/gnhash.h

diff --git a/ChangeLog b/ChangeLog
index 36113dc..aca1f7a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+10-11-12  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/dalvik/dop_aget.c:
+	* src/arch/dalvik/dop_aput.c:
+	* src/arch/dalvik/dop_arithm.c:
+	* src/arch/dalvik/dop_array.c:
+	* src/arch/dalvik/dop_const.c:
+	* src/arch/dalvik/dop_invoke.c:
+	Update code using pseudo registers.
+
+	* src/arch/dalvik/operand.c:
+	* src/arch/dalvik/register.c:
+	* src/arch/dalvik/register.h:
+	* src/arch/operand.c:
+	* src/arch/operand.h:
+	* src/arch/operand-int.h:
+	Add comparison methods to operands for being able to use them as keys
+	with the GLib maps.
+
+	* src/decomp/context.c:
+	* src/decomp/context.h:
+	Properly register pseudo registers.
+
+	* src/decomp/expr/pseudo.c:
+	* src/decomp/expr/pseudo.h:
+	Change the display of theses registers by using an index.
+
+	* src/glibext/gnhash.c:
+	* src/glibext/gnhash.h:
+	New entries: provide a new hash function for the GLib.
+
+	* src/glibext/Makefile.am:
+	Add the gnhash.[ch] files to libglibext_la_SOURCES.
+
 10-11-11  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/src/arch/dalvik/dop_aget.c b/src/arch/dalvik/dop_aget.c
index 77e6ef2..5ea57cc 100644
--- a/src/arch/dalvik/dop_aget.c
+++ b/src/arch/dalvik/dop_aget.c
@@ -52,13 +52,13 @@ GDecInstruction *dalvik_decomp_instr_aget(const GArchInstruction *instr, GDecCon
     GDecInstruction *access;                /* Représentation de l'accès   */
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    content = g_pseudo_register_new();
+    content = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    array = g_pseudo_register_new();
+    array = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    index = g_pseudo_register_new();
+    index = g_dec_context_convert_register(ctx, operand);
 
     access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index));
     result = g_assign_expression_new(G_DEC_EXPRESSION(content), G_DEC_EXPRESSION(access));
diff --git a/src/arch/dalvik/dop_aput.c b/src/arch/dalvik/dop_aput.c
index 2e4527e..3b75667 100644
--- a/src/arch/dalvik/dop_aput.c
+++ b/src/arch/dalvik/dop_aput.c
@@ -52,13 +52,13 @@ GDecInstruction *dalvik_decomp_instr_aput(const GArchInstruction *instr, GDecCon
     GDecInstruction *access;                /* Représentation de l'accès   */
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    content = g_pseudo_register_new();
+    content = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    array = g_pseudo_register_new();
+    array = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    index = g_pseudo_register_new();
+    index = g_dec_context_convert_register(ctx, operand);
 
     access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index));
     result = g_assign_expression_new(G_DEC_EXPRESSION(access), G_DEC_EXPRESSION(content));
diff --git a/src/arch/dalvik/dop_arithm.c b/src/arch/dalvik/dop_arithm.c
index 388f906..7657f99 100644
--- a/src/arch/dalvik/dop_arithm.c
+++ b/src/arch/dalvik/dop_arithm.c
@@ -51,7 +51,6 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr,
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *dest;                  /* Enregistrement du résultat  */
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
-    GDecInstruction *op2;                   /* Second opérande utilisé     */
     GDecInstruction *arithm;                /* Opération arithmétique      */
 
     switch (g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(instr)))
@@ -84,15 +83,12 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr,
     }
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_pseudo_register_new();
+    dest = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    op1 = g_pseudo_register_new();
-
-    operand = g_arch_instruction_get_operand(instr, 2);
-    op2 = g_pseudo_register_new();
+    op1 = g_dec_context_convert_register(ctx, operand);
 
-    arithm = g_arithm_expression_new(G_DEC_EXPRESSION(op1), type, G_DEC_EXPRESSION(op2));
+    arithm = g_arithm_expression_new(G_DEC_EXPRESSION(dest), type, G_DEC_EXPRESSION(op1));
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm));
 
     return result;
@@ -159,10 +155,10 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *instr, G
     }
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_pseudo_register_new();
+    dest = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    op1 = g_pseudo_register_new();
+    op1 = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 2);
     op2 = g_imm_expression_new(G_IMM_OPERAND(operand));
diff --git a/src/arch/dalvik/dop_array.c b/src/arch/dalvik/dop_array.c
index 035b3eb..fa9f94f 100644
--- a/src/arch/dalvik/dop_array.c
+++ b/src/arch/dalvik/dop_array.c
@@ -60,11 +60,11 @@ GDecInstruction *dalvik_decomp_instr_array_length(const GArchInstruction *instr,
 
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    reg = g_pseudo_register_new();
+    reg = g_dec_context_convert_register(ctx, operand);
     len = g_dalvik_alength_new(G_DEC_EXPRESSION(reg));
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    reg = g_pseudo_register_new();
+    reg = g_dec_context_convert_register(ctx, operand);
 
 
     result = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(len));
diff --git a/src/arch/dalvik/dop_const.c b/src/arch/dalvik/dop_const.c
index eab7acd..ea88089 100644
--- a/src/arch/dalvik/dop_const.c
+++ b/src/arch/dalvik/dop_const.c
@@ -59,8 +59,8 @@ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecCo
 
 
 
-    operand = g_arch_instruction_get_operand(instr, 1);
-    reg = g_pseudo_register_new();
+    operand = g_arch_instruction_get_operand(instr, 0);
+    reg = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 1);
     imm = g_imm_expression_new(G_IMM_OPERAND(operand));
diff --git a/src/arch/dalvik/dop_invoke.c b/src/arch/dalvik/dop_invoke.c
index e4fa1fb..6fdca06 100644
--- a/src/arch/dalvik/dop_invoke.c
+++ b/src/arch/dalvik/dop_invoke.c
@@ -117,7 +117,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
         //GDecInstruction *g_routine_call_new(GBinRoutine *routine, bool is_object)
     /*
     operand = g_arch_instruction_get_operand(instr, 1);
-    reg = g_pseudo_register_new();
+    reg = g_dec_context_convert_register(ctx, operand);
 
     operand = g_arch_instruction_get_operand(instr, 1);
     imm = g_imm_expression_new(G_IMM_OPERAND(operand));
@@ -141,8 +141,8 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
         {
             case DOP_MOVE_RESULT:
 
-                operand = g_arch_instruction_get_operand(instr, 0);
-                reg = g_pseudo_register_new();
+                operand = g_arch_instruction_get_operand(iter, 0);
+                reg = g_dec_context_convert_register(ctx, operand);
 
                 result = g_assign_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(result));
 
diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c
index 9c4a2c2..3227184 100644
--- a/src/arch/dalvik/operand.c
+++ b/src/arch/dalvik/operand.c
@@ -87,6 +87,9 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *);
 /* Initialise une instance d'opérande de registre Dalvik. */
 static void g_dalvik_register_operand_init(GDalvikRegisterOperand *);
 
+/* Compare un opérande avec un autre. */
+static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *, const GDalvikRegisterOperand *);
+
 /* Ajoute du texte simple à un fichier ouvert en écriture. */
 static void g_dalvik_register_operand_add_text(const GDalvikRegisterOperand *, GRenderingOptions *, MainRendering, FILE *);
 
@@ -325,13 +328,18 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *kl
 
 static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand)
 {
-    GContentExporter *parent;               /* Instance parente            */
+    GContentExporter *parent;               /* Instance parente #1         */
+    GArchOperand *arch;                     /* Instance parente #2         */
 
     parent = G_CONTENT_EXPORTER(operand);
 
     parent->add_text = (add_text_fc)g_dalvik_register_operand_add_text;
     parent->export_buffer = (export_buffer_fc)g_dalvik_register_operand_to_buffer;
 
+    arch = G_ARCH_OPERAND(operand);
+
+    arch->compare = (operand_compare_fc)g_dalvik_register_operand_compare;
+
 }
 
 
@@ -400,6 +408,26 @@ GArchOperand *g_dalvik_register_operand_new(const bin_t *data, off_t *pos, off_t
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : a = premier opérande à consulter.                            *
+*                b = second opérande à consulter.                             *
+*                                                                             *
+*  Description : Compare un opérande avec un autre.                           *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *a, const GDalvikRegisterOperand *b)
+{
+    return g_dalvik_register_compare(a->reg, b->reg);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : operand   = opérande à transcrire.                           *
 *                options   = options de rendu.                                *
 *                rendering = support effectif final des lignes de code.       *
diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c
index fc7757d..dd5a512 100644
--- a/src/arch/dalvik/register.c
+++ b/src/arch/dalvik/register.c
@@ -134,6 +134,35 @@ GDalvikRegister *g_dalvik_register_new(uint16_t index)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier opérande à consulter.                            *
+*                b = second opérande à consulter.                             *
+*                                                                             *
+*  Description : Compare un registre avec un autre.                           *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b)
+{
+    /* FIXME : GCC (Debian 4.4.5-4) trouble ? */
+
+    if (a == NULL)
+        printf("Alerte :: %hd & %hd\n", a->index, b->index);
+
+    /*
+    printf("Compare :: %p & %p\n", a, b);
+    printf("Compare :: %hd & %hd\n", a->index, b->index);
+    */
+
+    return (a->index == b->index);
+
+}
+
 
 /******************************************************************************
 *                                                                             *
diff --git a/src/arch/dalvik/register.h b/src/arch/dalvik/register.h
index 5ac5617..7767a9b 100644
--- a/src/arch/dalvik/register.h
+++ b/src/arch/dalvik/register.h
@@ -54,6 +54,9 @@ GType g_dalvik_register_get_type(void);
 /* Crée une réprésentation de registre Dalvik. */
 GDalvikRegister *g_dalvik_register_new(uint16_t);
 
+/* Compare un registre avec un autre. */
+bool g_dalvik_register_compare(const GDalvikRegister *, const GDalvikRegister *);
+
 /* Indique si le registre correspond à ebp ou similaire. */
 bool g_dalvik_register_is_base_pointer(const GDalvikRegister *);
 
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index f21b995..51f392b 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -30,17 +30,22 @@
 
 
 
+/* Compare un opérande avec un autre. */
+typedef bool (* operand_compare_fc) (const GArchOperand *, const GArchOperand *);
+
 /* Traduit un opérande en version humainement lisible. */
 typedef char * (* get_operand_text_fc) (const GArchOperand *, const GExeFormat *, AsmSyntax);
 
 /* Traduit un opérande en version humainement lisible. */
 typedef void (* operand_print_fc) (const GArchOperand *, GBufferLine *, AsmSyntax);
 
+
 /* Définition générique d'un opérande d'architecture (instance) */
 struct _GArchOperand
 {
     GContentExporter parent;                /* A laisser en premier        */
 
+    operand_compare_fc compare;             /* Comparaison d'opérandes     */
     get_operand_text_fc get_text;           /* Texte humain équivalent     */
     operand_print_fc print;                 /* Texte humain équivalent     */
 
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 16fc073..f3aecb6 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -117,3 +117,30 @@ void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line, AsmSyn
     return operand->print(operand, line, syntax);
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier opérande à consulter.                            *
+*                b = second opérande à consulter.                             *
+*                                                                             *
+*  Description : Compare un opérande avec un autre.                           *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b)
+{
+    bool result;                            /* Bilan à faire remonter      */
+
+    result = (G_OBJECT_TYPE(G_OBJECT(a)) == G_OBJECT_TYPE(G_OBJECT(b)));
+
+    if (result)
+        result = a->compare(a, b);
+
+    return result;
+
+}
diff --git a/src/arch/operand.h b/src/arch/operand.h
index 3745a80..d22235e 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -55,6 +55,9 @@ char *g_arch_operand_get_text(const GArchOperand *, const GExeFormat *, AsmSynta
 /* Traduit un opérande en version humainement lisible. */
 void g_arch_operand_print(const GArchOperand *, GBufferLine *, AsmSyntax);
 
+/* Compare un opérande avec un autre. */
+bool g_arch_operand_compare(const GArchOperand *, const GArchOperand *);
+
 
 
 #endif  /* _ARCH_OPERAND_H */
diff --git a/src/decomp/context.c b/src/decomp/context.c
index 7fe6937..6440c56 100644
--- a/src/decomp/context.c
+++ b/src/decomp/context.c
@@ -24,6 +24,14 @@
 #include "context.h"
 
 
+#include <malloc.h>
+
+
+#include "expr/pseudo.h"
+#include "../arch/operand.h"
+#include "../glibext/gnhash.h"
+
+
 
 /* Définition d'une context décompilée (instance) */
 struct _GDecContext
@@ -32,6 +40,12 @@ struct _GDecContext
 
     vmpa_t max;                             /* Première adresse à écarter  */
 
+    GHashTable *machine;                    /* Correspondance reg./pseudo  */
+    GHashTable *ssa;                        /* Remplacement des pseudos    */
+
+    GDecInstruction **pseudos;              /* Liste des pseudos-registre  */
+    size_t count;                           /* Taille de cette liste       */
+
 };
 
 
@@ -87,6 +101,8 @@ static void g_dec_context_class_init(GDecContextClass *klass)
 
 static void g_dec_context_init(GDecContext *ctx)
 {
+    ctx->machine = g_hash_table_new(g_constant_hash, (GEqualFunc)g_arch_operand_compare);
+    ctx->ssa = g_hash_table_new(NULL, NULL);
 
 }
 
@@ -151,3 +167,42 @@ void g_dec_context_set_max_address(GDecContext *ctx, vmpa_t max)
     ctx->max = max;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx     = instance à consulter, voire mettre à jour.         *
+*                operand = opérande représentant un registre quelconque.      *
+*                                                                             *
+*  Description : Convertit un registre machine en un pseudo-registre.         *
+*                                                                             *
+*  Retour      : Pseudo-registre, existant ou non, prêt à emploi.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand)
+{
+    GDecInstruction *result;                /* Instance à retourner        */
+    gpointer *found;                        /* Pseudo-registre trouvé      */
+
+    found = g_hash_table_lookup(ctx->machine, operand);
+
+    if (found != NULL) result = G_DEC_INSTRUCTION(found);
+    else
+    {
+        result = g_pseudo_register_new();
+        g_pseudo_register_set_index(G_PSEUDO_REGISTER(result), ctx->count);
+
+        g_hash_table_insert(ctx->machine, operand, result);
+
+        ctx->pseudos = (GDecInstruction **)realloc(ctx->pseudos,
+                                                   ++ctx->count * sizeof(GDecInstruction *));
+        ctx->pseudos[ctx->count - 1] = result;
+
+    }
+
+    return result;
+
+}
diff --git a/src/decomp/context.h b/src/decomp/context.h
index 76105e6..926a372 100644
--- a/src/decomp/context.h
+++ b/src/decomp/context.h
@@ -28,7 +28,7 @@
 #include <glib-object.h>
 
 
-#include "expr/pseudo.h"
+#include "instruction.h"
 #include "../arch/archbase.h"
 
 
@@ -61,6 +61,9 @@ vmpa_t g_dec_context_get_max_address(const GDecContext *);
 /* Définit l'adresse où la décompilation n'est plus souhaitée. */
 void g_dec_context_set_max_address(GDecContext *, vmpa_t);
 
+/* Convertit un registre machine en un pseudo-registre. */
+GDecInstruction *g_dec_context_convert_register(GDecContext *, gpointer);
+
 
 
 #endif  /* _DECOMP_CONTEXT_H */
diff --git a/src/decomp/expr/pseudo.c b/src/decomp/expr/pseudo.c
index 393f32c..abfcd4d 100644
--- a/src/decomp/expr/pseudo.c
+++ b/src/decomp/expr/pseudo.c
@@ -24,6 +24,10 @@
 #include "pseudo.h"
 
 
+#include <stdio.h>
+#include <string.h>
+
+
 #include "../expression-int.h"
 
 
@@ -33,6 +37,8 @@ struct _GPseudoRegister
 {
     GDecExpression parent;                  /* A laisser en premier        */
 
+    size_t index;                           /* Position dans l'ensemble    */
+
 };
 
 
@@ -141,8 +147,30 @@ GDecInstruction *g_pseudo_register_new(void)
 
 static void g_pseudo_register_print(const GPseudoRegister *reg, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)
 {
+    char label[32];
+
+    snprintf(label, 32, "var%d", reg->index);
+
+    g_buffer_line_insert_text(line, BLC_ASSEMBLY, label, strlen(label), RTT_RAW);
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY, "varX", 4, RTT_RAW);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : reg   = expression représentant un pseudo-registre à traiter.*
+*                index = indice à associer au pseudo-registre.                *
+*                                                                             *
+*  Description : Définit un indice unique pour un pseudo-registre donné.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+void g_pseudo_register_set_index(GPseudoRegister *reg, size_t index)
+{
+    reg->index = index;
 
 }
diff --git a/src/decomp/expr/pseudo.h b/src/decomp/expr/pseudo.h
index 9734625..95612a9 100644
--- a/src/decomp/expr/pseudo.h
+++ b/src/decomp/expr/pseudo.h
@@ -54,6 +54,9 @@ GType g_pseudo_register_get_type(void);
 /* Assigne le contenu d'une expression dans une autre. */
 GDecInstruction *g_pseudo_register_new(void);
 
+/* Définit un indice unique pour un pseudo-registre donné. */
+void g_pseudo_register_set_index(GPseudoRegister *, size_t);
+
 
 
 #endif  /* _DECOMP_EXPR_PSEUDO_H */
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index 1e21b58..2365190 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -7,6 +7,7 @@ libglibext_la_SOURCES =					\
 	gbufferline.h gbufferline.c			\
 	gbuffersegment.h gbuffersegment.c	\
 	gcodebuffer.h gcodebuffer.c			\
+	gnhash.h gnhash.c					\
 	proto.h
 
 libglibext_la_LDFLAGS = 
diff --git a/src/glibext/gnhash.c b/src/glibext/gnhash.c
new file mode 100644
index 0000000..cdd4dd1
--- /dev/null
+++ b/src/glibext/gnhash.c
@@ -0,0 +1,52 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gnhash.c - nouvelle fonction offrant une empreinte constante
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gnhash.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : v = pointeur quelconque.                                     *
+*                                                                             *
+*  Description : Convertit un pointeur en une empreinte constante.            *
+*                                                                             *
+*  Retour      : 2.                                                           *
+*                                                                             *
+*  Remarques   : L'algorithme actuel (12/11/10) de la GLib impose qu'une      *
+*                même empreinte impose une même clef. Deux clefs distinctes,  *
+*                pourtant égales, ont deux empreintes distinctes, donc on     *
+*                définit une seule empreinte possible. Pas terrible, mais     *
+*                cela répond au besoin (association simple clef <-> valeur).  *
+*                                                                             *
+******************************************************************************/
+
+guint g_constant_hash(gconstpointer v)
+{
+    /**
+     * La valeur doit être supérieure à 1 pour ne
+     * pas être totalement inéfficace.
+     */
+    return 2;
+
+}
diff --git a/src/glibext/gnhash.h b/src/glibext/gnhash.h
new file mode 100644
index 0000000..4c49357
--- /dev/null
+++ b/src/glibext/gnhash.h
@@ -0,0 +1,37 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gnhash.h - prototype pour une nouvelle fonction offrant une empreinte constante
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_GNHASH_H
+#define _GLIBEXT_GNHASH_H
+
+
+#include <glib-object.h>
+
+
+
+/* Convertit un pointeur en une empreinte constante. */
+guint g_constant_hash(gconstpointer);
+
+
+
+#endif  /* _GLIBEXT_GNHASH_H */
-- 
cgit v0.11.2-87-g4458