From 8e76324b01e5b4979f346f0bc8c84372477a3d38 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 10 May 2017 22:21:56 +0200
Subject: Rewritten the whole bitfield management.

---
 ChangeLog                           |  36 ++
 plugins/pychrysa/arch/vmpa.c        |  46 +--
 plugins/pychrysa/common/Makefile.am |   1 +
 plugins/pychrysa/common/bits.c      | 653 ++++++++++++++++++++++++++++++++++++
 plugins/pychrysa/common/bits.h      |  48 +++
 plugins/pychrysa/common/module.c    |   2 +
 plugins/pychrysa/format/symbol.c    |  39 +--
 plugins/pychrysa/helpers.c          |  54 +++
 plugins/pychrysa/helpers.h          |   3 +
 src/analysis/disass/area.c          |  57 +++-
 src/analysis/disass/dragon.c        |   2 +-
 src/common/bits.c                   | 293 +++++-----------
 src/common/bits.h                   |  22 +-
 tests/common/bitfield.py            | 106 ++++++
 tests/common/pathname.py            |   4 +-
 15 files changed, 1058 insertions(+), 308 deletions(-)
 create mode 100644 plugins/pychrysa/common/bits.c
 create mode 100644 plugins/pychrysa/common/bits.h
 create mode 100644 tests/common/bitfield.py

diff --git a/ChangeLog b/ChangeLog
index 123b47e..48e8334 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+17-05-10  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/arch/vmpa.c:
+	Typo. Update code.
+
+	* plugins/pychrysa/common/Makefile.am:
+	Add the 'bits.[ch]' files to libpychrysacommon_la_SOURCES.
+
+	* plugins/pychrysa/common/bits.c:
+	* plugins/pychrysa/common/bits.h:
+	New entries: provide Python bindings for bitfields.
+
+	* plugins/pychrysa/common/module.c:
+	Register the new bindings.
+
+	* plugins/pychrysa/format/symbol.c:
+	Typo. Update code.
+
+	* plugins/pychrysa/helpers.c:
+	* plugins/pychrysa/helpers.h:
+	Translate C comparison status to Python rich comparison status.
+
+	* src/analysis/disass/area.c:
+	* src/analysis/disass/dragon.c:
+	Update code.
+
+	* src/common/bits.c:
+	* src/common/bits.h:
+	Rewrite the whole bitfield management.
+
+	* tests/common/bitfield.py:
+	New entry: test the new bitfield bindings.
+
+	* tests/common/pathname.py:
+	Typo.
+
 17-05-08  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/raw.c:
diff --git a/plugins/pychrysa/arch/vmpa.c b/plugins/pychrysa/arch/vmpa.c
index 10acf35..03434d7 100644
--- a/plugins/pychrysa/arch/vmpa.c
+++ b/plugins/pychrysa/arch/vmpa.c
@@ -186,8 +186,9 @@ static PyObject *py_vmpa_to_str(PyObject *obj)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj  = objet Python à tenter de convertir.                   *
-*                addr = structure équivalente pour Chrysalide.                *
+*  Paramètres  : a  = premier object Python à consulter.                      *
+*                b  = second object Python à consulter.                       *
+*                op = type de comparaison menée.                              *
 *                                                                             *
 *  Description : Effectue une comparaison avec un objet Python 'vmpa_t'.      *
 *                                                                             *
@@ -199,7 +200,7 @@ static PyObject *py_vmpa_to_str(PyObject *obj)
 
 static PyObject *py_vmpa_richcompare(PyObject *a, PyObject *b, int op)
 {
-    PyObject *result;                       /* Chaîne à retourner          */
+    PyObject *result;                       /* Bilan à retourner           */
     vmpa2t *addr_a;                         /* Première adresse à traiter  */
     vmpa2t addr_b;                          /* Seconde adresse à traiter   */
 
@@ -829,8 +830,9 @@ static PyObject *py_mrange_to_str(PyObject *obj)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj  = objet Python à tenter de convertir.                   *
-*                addr = structure équivalente pour Chrysalide.                *
+*  Paramètres  : a  = premier object Python à consulter.                      *
+*                b  = second object Python à consulter.                       *
+*                op = type de comparaison menée.                              *
 *                                                                             *
 *  Description : Effectue une comparaison avec un objet Python 'mrange_t'.    *
 *                                                                             *
@@ -842,7 +844,7 @@ static PyObject *py_mrange_to_str(PyObject *obj)
 
 static PyObject *py_mrange_richcompare(PyObject *a, PyObject *b, int op)
 {
-    PyObject *result;                       /* Chaîne à retourner          */
+    PyObject *result;                       /* Bilan à retourner           */
     mrange_t *range_a;                      /* Premier espace à traiter    */
     mrange_t *range_b;                      /* Second espace à traiter     */
     int status;                             /* Résultat d'une comparaison  */
@@ -854,37 +856,7 @@ static PyObject *py_mrange_richcompare(PyObject *a, PyObject *b, int op)
 
     status = cmp_mrange(range_a, range_b);
 
-    switch (op)
-    {
-        case Py_LT:
-            result = status < 0 ? Py_True : Py_False;
-            break;
-
-        case Py_LE:
-            result = status <= 0 ? Py_True : Py_False;
-            break;
-
-        case Py_EQ:
-            result = status == 0 ? Py_True : Py_False;
-            break;
-
-        case Py_NE:
-            result = status != 0 ? Py_True : Py_False;
-            break;
-
-        case Py_GT:
-            result = status > 0 ? Py_True : Py_False;
-            break;
-
-        case Py_GE:
-            result = status >= 0 ? Py_True : Py_False;
-            break;
-
-        default:
-            result = Py_NotImplemented;
-            break;
-
-    }
+    result = status_to_rich_cmp_state(status, op);
 
     Py_INCREF(result);
 
diff --git a/plugins/pychrysa/common/Makefile.am b/plugins/pychrysa/common/Makefile.am
index 93d92ac..0637229 100644
--- a/plugins/pychrysa/common/Makefile.am
+++ b/plugins/pychrysa/common/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libpychrysacommon.la
 
 libpychrysacommon_la_SOURCES =			\
+	bits.h bits.c						\
 	fnv1a.h fnv1a.c						\
 	module.h module.c					\
 	pathname.h pathname.c
diff --git a/plugins/pychrysa/common/bits.c b/plugins/pychrysa/common/bits.c
new file mode 100644
index 0000000..33f81c3
--- /dev/null
+++ b/plugins/pychrysa/common/bits.c
@@ -0,0 +1,653 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.c - équivalent Python du fichier "common/bits.c"
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "bits.h"
+
+
+#include "../helpers.h"
+
+
+
+/* Encapsulation d'un champ de bits */
+typedef struct _py_bitfield_t
+{
+    PyObject_HEAD                           /* A laisser en premier        */
+
+    bitfield_t *native;                     /* Champ de bits représenté    */
+
+} py_bitfield_t;
+
+
+
+/* Crée un nouvel objet Python de type 'bitfield_t'. */
+static PyObject *py_bitfield_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Crée une copie d'un champ de bits classique. */
+static PyObject *py_bitfield_dup(PyObject *, PyObject *);
+
+/* Effectue une opération de type 'and' avec le type 'bitfield'. */
+static PyObject *py_bitfield_nb_and(PyObject *, PyObject *);
+
+/* Effectue une opération de type 'or' avec le type 'bitfield'. */
+static PyObject *py_bitfield_nb_or(PyObject *, PyObject *);
+
+/* Effectue une comparaison avec un objet Python 'bitfield'. */
+static PyObject *py_bitfield_richcompare(PyObject *, PyObject *, int);
+
+/* Bascule à 0 un champ de bits dans son intégralité. */
+static PyObject *py_bitfield_reset_all(PyObject *, PyObject *);
+
+/* Bascule à 1 un champ de bits dans son intégralité. */
+static PyObject *py_bitfield_set_all(PyObject *, PyObject *);
+
+/* Bascule à 0 une partie d'un champ de bits. */
+static PyObject *py_bitfield_reset(PyObject *, PyObject *);
+
+/* Bascule à 1 une partie d'un champ de bits. */
+static PyObject *py_bitfield_set(PyObject *, PyObject *);
+
+/* Détermine si un bit est à 1 dans un champ de bits. */
+static PyObject *py_bitfield_test(PyObject *, PyObject *);
+
+/* Détermine si un ensemble de bits est à 0 dans un champ. */
+static PyObject *py_bitfield_test_none(PyObject *, PyObject *);
+
+/* Détermine si un ensemble de bits est à 1 dans un champ. */
+static PyObject *py_bitfield_test_all(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type de l'objet à instancier.                         *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Crée un nouvel objet Python de type 'bitfield_t'.            *
+*                                                                             *
+*  Retour      : Instance Python mise en place.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    py_bitfield_t *result;                  /* Instance à retourner        */
+    unsigned long length;                   /* Taille du champ à créer     */
+    int state;                              /* Initialisation par défaut   */
+    int ret;                                /* Bilan de lecture des args.  */
+
+    ret = PyArg_ParseTuple(args, "kp", &length, &state);
+    if (!ret) return NULL;
+
+    result = (py_bitfield_t *)type->tp_alloc(type, 0);
+
+    result->native = create_bit_field(length, state);
+
+    return (PyObject *)result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à dupliquer.                            *
+*                args = non utilisé ici.                                      *
+*                                                                             *
+*  Description : Crée une copie d'un champ de bits classique.                 *
+*                                                                             *
+*  Retour      : Champ de bits mis en place.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_dup(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+
+    bf = (py_bitfield_t *)self;
+
+    result = build_from_internal_bitfield(bf->native);;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : o1 = premier élément concerné par l'opération.               *
+*                o2 = second élément concerné par l'opération.                *
+*                                                                             *
+*  Description : Effectue une opération de type 'and' avec le type 'bitfield'.*
+*                                                                             *
+*  Retour      : Résultat de l'opération.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_nb_and(PyObject *o1, PyObject *o2)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    int ret;                                /* Bilan de compatibilité      */
+    py_bitfield_t *bf_1;                    /* Instance à manipuler #1     */
+    py_bitfield_t *bf_2;                    /* Instance à manipuler #2     */
+    py_bitfield_t *new;                     /* Nouvelle version en place   */
+
+    ret = PyObject_IsInstance(o2, (PyObject *)get_python_bitfield_type());
+    if (!ret)
+    {
+        result = NULL;
+        goto pbna_done;
+    }
+
+    bf_1 = (py_bitfield_t *)o1;
+    bf_2 = (py_bitfield_t *)o2;
+
+    result = build_from_internal_bitfield(bf_1->native);
+
+    new = (py_bitfield_t *)result;
+
+    and_bit_field(new->native, bf_2->native);
+
+ pbna_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : o1 = premier élément concerné par l'opération.               *
+*                o2 = second élément concerné par l'opération.                *
+*                                                                             *
+*  Description : Effectue une opération de type 'or' avec le type 'bitfield'. *
+*                                                                             *
+*  Retour      : Résultat de l'opération.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_nb_or(PyObject *o1, PyObject *o2)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    int ret;                                /* Bilan de compatibilité      */
+    py_bitfield_t *bf_1;                    /* Instance à manipuler #1     */
+    py_bitfield_t *bf_2;                    /* Instance à manipuler #2     */
+    py_bitfield_t *new;                     /* Nouvelle version en place   */
+
+    ret = PyObject_IsInstance(o2, (PyObject *)get_python_bitfield_type());
+    if (!ret)
+    {
+        result = NULL;
+        goto pbna_done;
+    }
+
+    bf_1 = (py_bitfield_t *)o1;
+    bf_2 = (py_bitfield_t *)o2;
+
+    result = build_from_internal_bitfield(bf_1->native);
+
+    new = (py_bitfield_t *)result;
+
+    or_bit_field(new->native, bf_2->native);
+
+ pbna_done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a  = premier object Python à consulter.                      *
+*                b  = second object Python à consulter.                       *
+*                op = type de comparaison menée.                              *
+*                                                                             *
+*  Description : Effectue une comparaison avec un objet Python 'bitfield'.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_richcompare(PyObject *a, PyObject *b, int op)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_bitfield_t *bf_a;                    /* Instance à manipuler #1     */
+    py_bitfield_t *bf_b;                    /* Instance à manipuler #2     */
+    int status;                             /* Résultat d'une comparaison  */
+
+    ret = PyObject_IsInstance(b, (PyObject *)get_python_bitfield_type());
+    if (!ret)
+    {
+        result = Py_NotImplemented;
+        goto cmp_done;
+    }
+
+    bf_a = (py_bitfield_t *)a;
+    bf_b = (py_bitfield_t *)b;
+
+    status = compare_bit_fields(bf_a->native, bf_b->native);
+
+    result = status_to_rich_cmp_state(status, op);
+
+ cmp_done:
+
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à modifier.                             *
+*                args = non utilisé ici.                                      *
+*                                                                             *
+*  Description : Bascule à 0 un champ de bits dans son intégralité.           *
+*                                                                             *
+*  Retour      : Rien (None).                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_reset_all(PyObject *self, PyObject *args)
+{
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+
+    bf = (py_bitfield_t *)self;
+
+    reset_all_in_bit_field(bf->native);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à modifier.                             *
+*                args = non utilisé ici.                                      *
+*                                                                             *
+*  Description : Bascule à 1 un champ de bits dans son intégralité.           *
+*                                                                             *
+*  Retour      : Rien (None).                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_set_all(PyObject *self, PyObject *args)
+{
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+
+    bf = (py_bitfield_t *)self;
+
+    set_all_in_bit_field(bf->native);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à consulter.                            *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Bascule à 0 une partie d'un champ de bits.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_reset(PyObject *self, PyObject *args)
+{
+    unsigned long first;                    /* Indice du premier bit testé */
+    unsigned long count;                    /* Nombre de bits à analyser   */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+
+    ret = PyArg_ParseTuple(args, "kk", &first, &count);
+    if (!ret) return NULL;
+
+    bf = (py_bitfield_t *)self;
+
+    reset_in_bit_field(bf->native, first, count);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à consulter.                            *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Bascule à 1 une partie d'un champ de bits.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_set(PyObject *self, PyObject *args)
+{
+    unsigned long first;                    /* Indice du premier bit testé */
+    unsigned long count;                    /* Nombre de bits à analyser   */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+
+    ret = PyArg_ParseTuple(args, "kk", &first, &count);
+    if (!ret) return NULL;
+
+    bf = (py_bitfield_t *)self;
+
+    set_in_bit_field(bf->native, first, count);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à consulter.                            *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Détermine si un bit est à 1 dans un champ de bits.           *
+*                                                                             *
+*  Retour      : true si le bit correspondant est à l'état haut.              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_test(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à faire remonter      */
+    unsigned long n;                        /* Indice du bit à traiter     */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+    bool status;                            /* Bilan d'analyse             */
+
+    ret = PyArg_ParseTuple(args, "k", &n);
+    if (!ret) return NULL;
+
+    bf = (py_bitfield_t *)self;
+
+    status = test_in_bit_field(bf->native, n);
+
+    result = status ? Py_True : Py_False;
+
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à consulter.                            *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Détermine si un ensemble de bits est à 0 dans un champ.      *
+*                                                                             *
+*  Retour      : True si les bits correspondants sont à l'état bas.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_none(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à faire remonter      */
+    unsigned long first;                    /* Indice du premier bit testé */
+    unsigned long count;                    /* Nombre de bits à analyser   */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+    bool status;                            /* Bilan d'analyse             */
+
+    ret = PyArg_ParseTuple(args, "kk", &first, &count);
+    if (!ret) return NULL;
+
+    bf = (py_bitfield_t *)self;
+
+    status = test_none_in_bit_field(bf->native, first, count);
+
+    result = status ? Py_True : Py_False;
+
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = champ de bits à consulter.                            *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Détermine si un ensemble de bits est à 1 dans un champ.      *
+*                                                                             *
+*  Retour      : True si les bits correspondants sont à l'état haut.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_all(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à faire remonter      */
+    unsigned long first;                    /* Indice du premier bit testé */
+    unsigned long count;                    /* Nombre de bits à analyser   */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_bitfield_t *bf;                      /* Instance à manipuler        */
+    bool status;                            /* Bilan d'analyse             */
+
+    ret = PyArg_ParseTuple(args, "kk", &first, &count);
+    if (!ret) return NULL;
+
+    bf = (py_bitfield_t *)self;
+
+    status = test_all_in_bit_field(bf->native, first, count);
+
+    result = status ? Py_True : Py_False;
+
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_bitfield_type(void)
+{
+    static PyNumberMethods py_bitfield_nb_proto = {
+
+        .nb_and = py_bitfield_nb_and,
+        .nb_or = py_bitfield_nb_or
+
+    };
+
+    static PyMethodDef py_bitfield_methods[] = {
+        {
+            "dup", py_bitfield_dup,
+            METH_NOARGS,
+            "dup(self, /)\n--\n\nDuplicate a bitfield."
+        },
+        {
+            "reset_all", py_bitfield_reset_all,
+            METH_NOARGS,
+            "reset_all(self, /)\n--\n\nSwitch to 0 all bits in a bitfield."
+        },
+        {
+            "set_all", py_bitfield_set_all,
+            METH_NOARGS,
+            "set_all(self, /)\n--\n\nSwitch to 1 all bits in a bitfield."
+        },
+        {
+            "reset", py_bitfield_reset,
+            METH_VARARGS,
+            "reset(self, first, count, /)\n--\n\nSwitch to 0 a part of bits in a bitfield."
+        },
+        {
+            "set", py_bitfield_set,
+            METH_VARARGS,
+            "set(self, first, count, /)\n--\n\nSwitch to 1 a part of bits in a bitfield."
+        },
+        {
+            "test", py_bitfield_test,
+            METH_VARARGS,
+            "test(self, n, /)\n--\n\nTest if a given bit is set in a bitfield."
+        },
+        {
+            "test_none", py_bitfield_test_none,
+            METH_VARARGS,
+            "test_none(self, first, count, /)\n--\n\nTest a range of bits to 0."
+        },
+        {
+            "test_all", py_bitfield_test_all,
+            METH_VARARGS,
+            "test_all(self, first, count, /)\n--\n\nTest a range of bits to 1."
+        },
+        { NULL }
+    };
+
+    static PyGetSetDef py_bitfield_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_bitfield_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.common.bitfield",
+        .tp_basicsize   = sizeof(py_bitfield_t),
+
+        .tp_as_number   = &py_bitfield_nb_proto,
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = "Python object for bitfield_t.",
+
+        .tp_richcompare = py_bitfield_richcompare,
+
+        .tp_methods     = py_bitfield_methods,
+        .tp_getset      = py_bitfield_getseters,
+        .tp_new         = (newfunc)py_bitfield_new
+
+    };
+
+    return &py_bitfield_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.common.bitfield'.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_bitfield(PyObject *module)
+{
+    PyTypeObject *py_bitfield_type;         /* Type Python pour 'bitfield' */
+    int ret;                                /* Bilan d'un appel            */
+
+    py_bitfield_type = get_python_bitfield_type();
+
+    if (PyType_Ready(py_bitfield_type) != 0)
+        return false;
+
+    Py_INCREF(py_bitfield_type);
+    ret = PyModule_AddObject(module, "bitfield", (PyObject *)py_bitfield_type);
+
+    return (ret == 0);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : field = structure interne à copier en objet Python.          *
+*                                                                             *
+*  Description : Convertit une structure de type 'bitfield' en objet Python.  *
+*                                                                             *
+*  Retour      : Object Python résultant de la conversion opérée.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *build_from_internal_bitfield(const bitfield_t *field)
+{
+    py_bitfield_t *result;                  /* Instance à retourner        */
+    PyTypeObject *type;                     /* Type à instancier           */
+
+    type = get_python_bitfield_type();
+
+    result = (py_bitfield_t *)type->tp_alloc(type, 0);
+
+    result->native = dup_bit_field(field);
+
+    return (PyObject *)result;
+
+}
diff --git a/plugins/pychrysa/common/bits.h b/plugins/pychrysa/common/bits.h
new file mode 100644
index 0000000..41465ce
--- /dev/null
+++ b/plugins/pychrysa/common/bits.h
@@ -0,0 +1,48 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour l'équivalent Python du fichier "common/bits.h"
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSA_COMMON_BITS_H
+#define _PLUGINS_PYCHRYSA_COMMON_BITS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+#include <common/bits.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_bitfield_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.common.bitfield'. */
+bool register_python_bitfield(PyObject *);
+
+/* Convertit une structure de type 'bitfield' en objet Python. */
+PyObject *build_from_internal_bitfield(const bitfield_t *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSA_COMMON_BITS_H */
diff --git a/plugins/pychrysa/common/module.c b/plugins/pychrysa/common/module.c
index cc23631..cc2623a 100644
--- a/plugins/pychrysa/common/module.c
+++ b/plugins/pychrysa/common/module.c
@@ -25,6 +25,7 @@
 #include "module.h"
 
 
+#include "bits.h"
 #include "fnv1a.h"
 #include "pathname.h"
 
@@ -76,6 +77,7 @@ bool add_common_module_to_python_module(PyObject *super)
 
     result = true;
 
+    result &= register_python_bitfield(module);
     result &= register_python_fnv1a(module);
     result &= register_python_pathname(module);
 
diff --git a/plugins/pychrysa/format/symbol.c b/plugins/pychrysa/format/symbol.c
index 53fb9c9..75f226a 100644
--- a/plugins/pychrysa/format/symbol.c
+++ b/plugins/pychrysa/format/symbol.c
@@ -85,8 +85,9 @@ static bool py_binary_symbol_define_constants(PyTypeObject *);
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj  = objet Python à tenter de convertir.                   *
-*                addr = structure équivalente pour Chrysalide.                *
+*  Paramètres  : a  = premier object Python à consulter.                      *
+*                b  = second object Python à consulter.                       *
+*                op = type de comparaison menée.                              *
 *                                                                             *
 *  Description : Effectue une comparaison avec un objet Python 'BinSymbol'.   *
 *                                                                             *
@@ -98,7 +99,7 @@ static bool py_binary_symbol_define_constants(PyTypeObject *);
 
 static PyObject *py_binary_symbol_richcompare(PyObject *a, PyObject *b, int op)
 {
-    PyObject *result;                       /* Chaîne à retourner          */
+    PyObject *result;                       /* Bilan à retourner           */
     int ret;                                /* Bilan de lecture des args.  */
     const GBinSymbol *sym_a;                /* Premier élément à traiter   */
     const GBinSymbol *sym_b;                /* Second élément à traiter    */
@@ -116,37 +117,7 @@ static PyObject *py_binary_symbol_richcompare(PyObject *a, PyObject *b, int op)
 
     status = g_binary_symbol_cmp(&sym_a, &sym_b);
 
-    switch (op)
-    {
-        case Py_LT:
-            result = status < 0 ? Py_True : Py_False;
-            break;
-
-        case Py_LE:
-            result = status <= 0 ? Py_True : Py_False;
-            break;
-
-        case Py_EQ:
-            result = status == 0 ? Py_True : Py_False;
-            break;
-
-        case Py_NE:
-            result = status != 0 ? Py_True : Py_False;
-            break;
-
-        case Py_GT:
-            result = status > 0 ? Py_True : Py_False;
-            break;
-
-        case Py_GE:
-            result = status >= 0 ? Py_True : Py_False;
-            break;
-
-        default:
-            result = Py_NotImplemented;
-            break;
-
-    }
+    result = status_to_rich_cmp_state(status, op);
 
  cmp_done:
 
diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c
index 36d0d76..df1df05 100644
--- a/plugins/pychrysa/helpers.c
+++ b/plugins/pychrysa/helpers.c
@@ -31,6 +31,60 @@
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : status = bilan de comparaison à traduire.                    *
+*                op     = type de comparaison menée.                          *
+*                                                                             *
+*  Description : Traduit pour Python le bilan d'une comparaison riche.        *
+*                                                                             *
+*  Retour      : Objet Python à référencer.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *status_to_rich_cmp_state(int status, int op)
+{
+    PyObject *result;                       /* Bilan àretourner            */
+
+    switch (op)
+    {
+        case Py_LT:
+            result = status < 0 ? Py_True : Py_False;
+            break;
+
+        case Py_LE:
+            result = status <= 0 ? Py_True : Py_False;
+            break;
+
+        case Py_EQ:
+            result = status == 0 ? Py_True : Py_False;
+            break;
+
+        case Py_NE:
+            result = status != 0 ? Py_True : Py_False;
+            break;
+
+        case Py_GT:
+            result = status > 0 ? Py_True : Py_False;
+            break;
+
+        case Py_GE:
+            result = status >= 0 ? Py_True : Py_False;
+            break;
+
+        default:
+            result = Py_NotImplemented;
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : target = propriétaire de la routine visée.                   *
 *                method = désignation de la fonction à appeler.               *
 *                                                                             *
diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h
index 3e079b7..950c85b 100644
--- a/plugins/pychrysa/helpers.h
+++ b/plugins/pychrysa/helpers.h
@@ -31,6 +31,9 @@
 
 
 
+/* Traduit pour Python le bilan d'une comparaison riche. */
+PyObject *status_to_rich_cmp_state(int, int);
+
 /* Indique si une routine Python existe ou non. */
 bool has_python_method(PyObject *, const char *);
 
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index f01b89c..ed53b28 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -60,6 +60,7 @@ typedef struct _mem_area
     bitfield_t *processed;                  /* Octets traités dans la zone */
     GArchInstruction **instructions;        /* Instructions en place       */
     size_t count;                           /* Quantité d'instructions     */
+    GMutex mutex;                           /* Garantie d'atomicité        */
 
     bool is_exec;                           /* Zone exécutable ?           */
 
@@ -249,6 +250,7 @@ static void init_mem_area_from_addr(mem_area *area, const vmpa2t *addr, phys_t l
     area->processed = create_bit_field(len, false);
     area->instructions = (GArchInstruction **)calloc(len, sizeof(GArchInstruction *));
     area->count = 0;
+    g_mutex_init(&area->mutex);
 
 }
 
@@ -284,6 +286,8 @@ static void fini_mem_area(mem_area *area)
 
     free(area->instructions);
 
+    g_mutex_clear(&area->mutex);
+
 }
 
 
@@ -365,6 +369,10 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
     phys_t offset;                          /* Décallage de départ         */
     phys_t i;                               /* Boucle de parcours          */
     GArchInstruction *old;                  /* Instruction remplacée       */
+    const mrange_t *old_range;              /* Emplacement de l'instruction*/
+    phys_t old_len;                         /* Taille de cette instruction */
+
+    /* Détermination de la couverture */
 
     start = get_mrange_addr(&area->range);
 
@@ -374,21 +382,23 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
 
     offset = compute_vmpa_diff(start, addr);
 
-    result = set_atomic_in_bit_field(area->processed, offset, len);
+    /* Début des choses sérieuses */
+
+    g_mutex_lock(&area->mutex);
 
-    /* Si l'instruction était bien la première à s'inscrire... */
+    /* Vérification de couverture */
 
-    result |= force;
+    result = test_none_in_bit_field(area->processed, offset, len);
 
-    if (result)
+    if (!result)
     {
-        assert(area->instructions[offset] == NULL || force);
+        if (!force) goto mrimaap_exit;
 
         /**
          * Un cas de remplacement forcé intervient en ARM, lorsque qu'une
          * instruction utilise une valeur immédiate placée dans le code.
          *
-         * Cette valeur est référencée en tant que symbole.
+         * Cette valeur doit être référencée en tant que donnée.
          *
          * Mais cette même valeur a pu être désassemblée en tant que code
          * exécutable si le flot d'exécution s'est poursuivi jusqu'à elle.
@@ -400,33 +410,52 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
          * On réinitialise donc la zone couverte par la nouvelle instruction.
          */
 
-        for (i = 0; force && i < len; i++)
+        for (i = 0; i < len; i++)
         {
             old = area->instructions[offset + i];
 
             if (old != NULL)
             {
+                old_range = g_arch_instruction_get_range(old);
+                old_len = get_mrange_length(old_range);
+
+                reset_in_bit_field(area->processed, offset + i, old_len);
+
                 g_object_unref(G_OBJECT(old));
                 area->instructions[offset + i] = NULL;
+
                 g_atomic_pointer_add(&area->count, -1);
+
             }
 
         }
 
+        result = true;
+
+    }
+
+    /* Inscription de l'instruction dans les comptes */
+
 #ifndef NDEBUG
 
-        for (i = 0; i < len; i++)
-            assert(area->instructions[offset + i] == NULL);
+    for (i = 0; i < len; i++)
+        assert(area->instructions[offset + i] == NULL);
 
 #endif
 
-        area->instructions[offset] = instr;
-        g_atomic_pointer_add(&area->count, 1);
+    set_in_bit_field(area->processed, offset, len);
 
-        /* Au passage, association du contenu */
-        g_arch_instruction_set_global_content(instr, area->content);
+    area->instructions[offset] = instr;
+    g_atomic_pointer_add(&area->count, 1);
 
-    }
+    /* Au passage, association du contenu */
+    g_arch_instruction_set_global_content(instr, area->content);
+
+ mrimaap_exit:
+
+    /* Fin des choses sérieuses */
+
+    g_mutex_unlock(&area->mutex);
 
     return result;
 
diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c
index 75ccc40..9064af8 100644
--- a/src/analysis/disass/dragon.c
+++ b/src/analysis/disass/dragon.c
@@ -591,7 +591,7 @@ void compute_all_dominators(dragon_node *nodes, size_t count)
 
             set_in_bit_field(inter, k, 1);
 
-            if (!is_bit_field_equal_to(node->bits, inter))
+            if (compare_bit_fields(node->bits, inter) != 0)
             {
                 copy_bit_field(node->bits, inter);
                 changed = true;
diff --git a/src/common/bits.c b/src/common/bits.c
index d4d5074..4d4731a 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -37,22 +37,13 @@ struct _bitfield_t
     size_t length;                          /* Nombre de bits représentés  */
     size_t requested;                       /* Nombre de mots alloués      */
 
-    void *tail;                             /* Limite du tableau de bits   */
-
-    GMutex mutex;                           /* Garantie d'atomicité        */
     unsigned long bits[0];                  /* Mémoire d'accès associée    */
 
 };
 
 
 /* Crée un champ de bits initialisé à zéro. */
-static bitfield_t *_create_bit_field(size_t, bool, size_t);
-
-/* Crée une copie de champ de bits initialisé à zéro. */
-static bitfield_t *_create_bit_field_from(const bitfield_t *, bool, size_t);
-
-/* Crée une copie d'un champ de bits classique. */
-static bitfield_t *_dup_bit_field(const bitfield_t *, size_t);
+static bitfield_t *_create_bit_field(size_t);
 
 /* Détermine si un ensemble de bits est homogène dans un champ. */
 static bool test_state_in_bit_field(const bitfield_t *, size_t, size_t, bool);
@@ -62,8 +53,6 @@ static bool test_state_in_bit_field(const bitfield_t *, size_t, size_t, bool);
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : length = nom de bits du champ à représenter.                 *
-*                state  = état initial de chaque des bits.                    *
-*                extra  = espace mémoire supplémentaire à ajouter au final.   *
 *                                                                             *
 *  Description : Crée un champ de bits initialisé à zéro.                     *
 *                                                                             *
@@ -73,31 +62,22 @@ static bool test_state_in_bit_field(const bitfield_t *, size_t, size_t, bool);
 *                                                                             *
 ******************************************************************************/
 
-static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
+static bitfield_t *_create_bit_field(size_t length)
 {
     bitfield_t *result;                     /* Création à retourner        */
     size_t requested;                       /* Nombre de mots à allouer    */
     size_t base;                            /* Allocation de base en octets*/
 
-    requested = length / sizeof(unsigned long);
-    if (length % sizeof(unsigned long) != 0) requested++;
+    requested = length / (sizeof(unsigned long) * 8);
+    if (length % (sizeof(unsigned long) * 8) != 0) requested++;
 
     base = sizeof(bitfield_t) + requested * sizeof(unsigned long);
 
-    result = (bitfield_t *)malloc(base + extra);
+    result = (bitfield_t *)malloc(base);
 
     result->length = length;
     result->requested = requested;
 
-    result->tail = ((char *)result) + base;
-
-    g_mutex_init(&result->mutex);
-
-    if (state)
-        set_all_in_bit_field(result);
-    else
-        reset_all_in_bit_field(result);
-
     return result;
 
 }
@@ -105,7 +85,7 @@ static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : length = nom de bits du champ à représenter.                 *
+*  Paramètres  : length = nombre de bits du champ à représenter.              *
 *                state  = état initial de chaque des bits.                    *
 *                                                                             *
 *  Description : Crée un champ de bits initialisé.                            *
@@ -118,38 +98,25 @@ static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
 
 bitfield_t *create_bit_field(size_t length, bool state)
 {
-    return _create_bit_field(length, state, 0);
-
-}
+    bitfield_t *result;                     /* Création à retourner        */
 
+    result = _create_bit_field(length);
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : field = champde bits à prendre pour modèle.                  *
-*                state = état initial de chaque des bits.                     *
-*                extra = espace mémoire supplémentaire à ajouter au final.    *
-*                                                                             *
-*  Description : Crée une copie de champ de bits initialisé à zéro.           *
-*                                                                             *
-*  Retour      : Champ de bits mis en place.                                  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    if (state)
+        set_all_in_bit_field(result);
+    else
+        reset_all_in_bit_field(result);
 
-static bitfield_t *_create_bit_field_from(const bitfield_t *field, bool state, size_t extra)
-{
-    return _create_bit_field(field->length, state, extra);
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : field = champde bits à prendre pour modèle.                  *
-*                state = état initial de chaque des bits.                     *
+*  Paramètres  : field = champ de bits à dupliquer.                           *
 *                                                                             *
-*  Description : Crée une copie de champ de bits initialisé à zéro.           *
+*  Description : Crée une copie d'un champ de bits classique.                 *
 *                                                                             *
 *  Retour      : Champ de bits mis en place.                                  *
 *                                                                             *
@@ -157,9 +124,15 @@ static bitfield_t *_create_bit_field_from(const bitfield_t *field, bool state, s
 *                                                                             *
 ******************************************************************************/
 
-bitfield_t *create_bit_field_from(const bitfield_t *field, bool state)
+bitfield_t *dup_bit_field(const bitfield_t *field)
 {
-    return _create_bit_field_from(field, state, 0);
+    bitfield_t *result;                     /* Copie à retourner           */
+
+    result = _create_bit_field(field->length);
+
+    memcpy(result->bits, field->bits, result->requested * sizeof(unsigned long));
+
+    return result;
 
 }
 
@@ -178,8 +151,6 @@ bitfield_t *create_bit_field_from(const bitfield_t *field, bool state)
 
 void delete_bit_field(bitfield_t *field)
 {
-    g_mutex_clear(&field->mutex);
-
     free(field);
 
 }
@@ -209,49 +180,64 @@ void copy_bit_field(bitfield_t *dest, const bitfield_t *src)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : field = champ de bits à dupliquer.                           *
-*                extra = espace mémoire supplémentaire à ajouter au final.    *
+*  Paramètres  : a = premier champ à analyser.                                *
+*                b = second champ à analyser.                                 *
 *                                                                             *
-*  Description : Crée une copie d'un champ de bits classique.                 *
+*  Description : Compare deux champs de bits entre eux.                       *
 *                                                                             *
-*  Retour      : Champ de bits mis en place.                                  *
+*  Retour      : Bilan de la comparaison.                                     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bitfield_t *_dup_bit_field(const bitfield_t *field, size_t extra)
+int compare_bit_fields(const bitfield_t *a, const bitfield_t *b)
 {
-    bitfield_t *result;                     /* Copie à retourner           */
-    size_t requested;                       /* Nombre de mots à allouer    */
+    int result;                             /* Bilan à retourner           */
+    unsigned long final;                    /* Masque de la partie finale  */
+    size_t i;                               /* Boucle de parcours          */
+    unsigned long val_a;                    /* Valeur d'un mot de A        */
+    unsigned long val_b;                    /* Valeur d'un mot de B        */
 
-    result = _create_bit_field(field->length, false, extra);
+    result = 0;
 
-    requested = field->length / sizeof(unsigned long);
-    if (field->length % sizeof(unsigned long) != 0) requested++;
+    if (a->length > b->length)
+        result = 1;
 
-    memcpy(result->bits, field->bits, requested * sizeof(unsigned long));
+    else if (a->length < b->length)
+        result = -1;
 
-    return result;
+    if (result == 0)
+    {
+        final = a->length % sizeof(unsigned long);
 
-}
+        if (final == 0)
+            final = ~0lu;
+        else
+            final = (1 << final) - 1;
 
+        for (i = 0; i < a->requested && result == 0; i++)
+        {
+            val_a = a->bits[i];
+            val_b = b->bits[i];
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : field = champ de bits à dupliquer.                           *
-*                                                                             *
-*  Description : Crée une copie d'un champ de bits classique.                 *
-*                                                                             *
-*  Retour      : Champ de bits mis en place.                                  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+            if ((i + 1) == a->requested)
+            {
+                val_a &= final;
+                val_b &= final;
+            }
 
-bitfield_t *dup_bit_field(const bitfield_t *field)
-{
-    return _dup_bit_field(field, 0);
+            if (val_a > val_b)
+                result = 1;
+
+            else if (val_a < val_b)
+                result = -1;
+
+        }
+
+    }
+
+    return result;
 
 }
 
@@ -300,7 +286,7 @@ void set_all_in_bit_field(bitfield_t *field)
 *                first = indice du premier bit à traiter.                     *
 *                count = nombre de bits à marquer.                            *
 *                                                                             *
-*  Description : Bascule à 1 une partie d'un champ de bits.                   *
+*  Description : Bascule à 0 une partie d'un champ de bits.                   *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -308,7 +294,7 @@ void set_all_in_bit_field(bitfield_t *field)
 *                                                                             *
 ******************************************************************************/
 
-void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
+void reset_in_bit_field(bitfield_t *field, size_t first, size_t count)
 {
     size_t last;                            /* Point d'arrêt de la boucle  */
     size_t i;                               /* Boucle de parcours          */
@@ -324,7 +310,7 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
         index = i / (sizeof(unsigned long) * 8);
         remaining = i % (sizeof(unsigned long) * 8);
 
-        field->bits[index] |= (1ul << remaining);
+        field->bits[index] &= ~(1ul << remaining);
 
     }
 
@@ -337,79 +323,34 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
 *                first = indice du premier bit à traiter.                     *
 *                count = nombre de bits à marquer.                            *
 *                                                                             *
-*  Description : Bascule à 1 de façon atomique une partie d'un champ de bits. *
+*  Description : Bascule à 1 une partie d'un champ de bits.                   *
 *                                                                             *
-*  Retour      : true si la zone traitée était entièrement vierge.            *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool set_atomic_in_bit_field(bitfield_t *field, size_t first, size_t count)
+void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
 {
-    bool result;                            /* Bilan à retourner           */
-    size_t start;                           /* Mot de départ               */
-    size_t end;                             /* Mot d'arrivée               */
+    size_t last;                            /* Point d'arrêt de la boucle  */
+    size_t i;                               /* Boucle de parcours          */
+    size_t index;                           /* Cellule de tableau visée    */
     size_t remaining;                       /* Nombre de bits restants     */
-    unsigned long mask;                     /* Nouvelle valeur à insérer   */
-    unsigned long oldval;                   /* Ancienne valeur présente    */
-
-    start = first / (sizeof(unsigned long) * 8);
-    end = (first + count - 1) / (sizeof(unsigned long) * 8);
-
-    if (start == end)
-    {
-        remaining = first % (sizeof(unsigned long) * 8);
 
-        assert(count > 0 && count <= (sizeof(unsigned long) * 8));
-
-        if (count == 64)
-        {
-            assert(remaining == 0);
-            mask = ~0lu;
-        }
-        else
-        {
-            mask = (1lu << count) - 1;
-            mask <<= remaining;
-        }
-
-        /**
-         * Pour une raison inconnue, l'appel suivant est parfois sans effet :
-         *
-         *    oldval = g_atomic_pointer_or(&field->bits[start], mask);
-         *
-         * On bascule donc dans l'équivalent plus long à exécuter...
-         */
-
-        g_mutex_lock(&field->mutex);
-
-        oldval = field->bits[start];
-
-        field->bits[start] |= mask;
-
-        g_mutex_unlock(&field->mutex);
-
-        result = ((oldval & mask) == 0);
+    last = first + count;
 
-        assert(test_all_in_bit_field(field, first, count));
+    assert(last <= field->length);
 
-    }
-    else
+    for (i = first; i < last; i++)
     {
-        g_mutex_lock(&field->mutex);
-
-        result = test_none_in_bit_field(field, first, count);
-
-        if (result)
-            set_in_bit_field(field, first, count);
+        index = i / (sizeof(unsigned long) * 8);
+        remaining = i % (sizeof(unsigned long) * 8);
 
-        g_mutex_unlock(&field->mutex);
+        field->bits[index] |= (1ul << remaining);
 
     }
 
-    return result;
-
 }
 
 
@@ -465,7 +406,7 @@ void or_bit_field(bitfield_t *dest, const bitfield_t *src)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : field = champ de bits à modifier.                            *
+*  Paramètres  : field = champ de bits à consulter.                           *
 *                n     = indice du bit à traiter.                             *
 *                                                                             *
 *  Description : Détermine si un bit est à 1 dans un champ de bits.           *
@@ -503,7 +444,7 @@ bool test_in_bit_field(const bitfield_t *field, size_t n)
 *                                                                             *
 *  Description : Détermine si un ensemble de bits est homogène dans un champ. *
 *                                                                             *
-*  Retour      : true si le bit correspondant est à l'état haut.              *
+*  Retour      : true si les bits correspondants sont à l'état indiqué.       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -539,13 +480,13 @@ static bool test_state_in_bit_field(const bitfield_t *field, size_t first, size_
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : field = champ de bits à modifier.                            *
+*  Paramètres  : field = champ de bits à consulter.                           *
 *                first = indice du premier bit à traiter.                     *
-*                count = nombre de bits à marquer.                            *
+*                count = nombre de bits à analyser.                           *
 *                                                                             *
 *  Description : Détermine si un ensemble de bits est à 0 dans un champ.      *
 *                                                                             *
-*  Retour      : true si le bit correspondant est à l'état haut.              *
+*  Retour      : true si les bits correspondants sont à l'état bas.           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -564,13 +505,13 @@ bool test_none_in_bit_field(const bitfield_t *field, size_t first, size_t count)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : field = champ de bits à modifier.                            *
+*  Paramètres  : field = champ de bits à consulter.                           *
 *                first = indice du premier bit à traiter.                     *
-*                count = nombre de bits à marquer.                            *
+*                count = nombre de bits à analyser.                           *
 *                                                                             *
 *  Description : Détermine si un ensemble de bits est à 1 dans un champ.      *
 *                                                                             *
-*  Retour      : true si le bit correspondant est à l'état haut.              *
+*  Retour      : true si les bits correspondants sont à l'état haut.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -585,61 +526,3 @@ bool test_all_in_bit_field(const bitfield_t *field, size_t first, size_t count)
     return result;
 
 }
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : a = premier champ de bits à comparer.                        *
-*                b = second champ de bits à comparer.                         *
-*                                                                             *
-*  Description : Indique si deux champs de bits sont identiques ou non.       *
-*                                                                             *
-*  Retour      : true si les champs de bits sont égaux ou false sinon.        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool is_bit_field_equal_to(const bitfield_t *a, const bitfield_t *b)
-{
-    bool result;                            /* Résultat à retourner        */
-    size_t i;                               /* Boucle de parcours          */
-    size_t remaining;                       /* Nombre de bits restants     */
-
-    if (a->length != b->length)
-        return false;
-
-    result = true;
-
-    for (i = 0; i < (a->requested - 1) && result; i++)
-        result = (a->bits[i] == b->bits[i]);
-
-    if (result)
-    {
-        remaining = a->length % sizeof(unsigned long);
-
-        if (remaining == 0)
-            result = (a->bits[i] == b->bits[i]);
-
-        else
-        {
-            remaining = (1 << (remaining + 1)) - 1;
-
-            result = ((a->bits[i] & remaining) == (b->bits[i] & remaining));
-
-        }
-
-    }
-
-    return result;
-
-}
-
-
-
-
-unsigned long gfw(const bitfield_t *field)
-{
-    return field->bits[0];
-
-}
diff --git a/src/common/bits.h b/src/common/bits.h
index 4a2937f..b9fc0e6 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -36,8 +36,8 @@ typedef struct _bitfield_t bitfield_t;
 /* Crée un champ de bits initialisé. */
 bitfield_t *create_bit_field(size_t, bool);
 
-/* Crée une copie de champ de bits initialisé à zéro. */
-bitfield_t *create_bit_field_from(const bitfield_t *, bool);
+/* Crée une copie d'un champ de bits classique. */
+bitfield_t *dup_bit_field(const bitfield_t *);
 
 /* Supprime de la mémoire un champ de bits donné. */
 void delete_bit_field(bitfield_t *);
@@ -45,8 +45,8 @@ void delete_bit_field(bitfield_t *);
 /* Copie un champ de bits dans un autre. */
 void copy_bit_field(bitfield_t *, const bitfield_t *);
 
-/* Crée une copie d'un champ de bits classique. */
-bitfield_t *dup_bit_field(const bitfield_t *);
+/* Compare deux champs de bits entre eux. */
+int compare_bit_fields(const bitfield_t *, const bitfield_t *);
 
 /* Bascule à 0 un champ de bits dans son intégralité. */
 void reset_all_in_bit_field(bitfield_t *);
@@ -54,12 +54,12 @@ void reset_all_in_bit_field(bitfield_t *);
 /* Bascule à 1 un champ de bits dans son intégralité. */
 void set_all_in_bit_field(bitfield_t *);
 
+/* Bascule à 0 une partie d'un champ de bits. */
+void reset_in_bit_field(bitfield_t *, size_t, size_t);
+
 /* Bascule à 1 une partie d'un champ de bits. */
 void set_in_bit_field(bitfield_t *, size_t, size_t);
 
-/* Bascule à 1 de façon atomique une partie d'un champ de bits. */
-bool set_atomic_in_bit_field(bitfield_t *, size_t, size_t);
-
 /* Réalise une opération ET logique entre deux champs de bits. */
 void and_bit_field(bitfield_t *, const bitfield_t *);
 
@@ -75,14 +75,6 @@ bool test_none_in_bit_field(const bitfield_t *, size_t, size_t);
 /* Détermine si un ensemble de bits est à 1 dans un champ. */
 bool test_all_in_bit_field(const bitfield_t *, size_t, size_t);
 
-/* Indique si deux champs de bits sont identiques ou non. */
-bool is_bit_field_equal_to(const bitfield_t *, const bitfield_t *);
-
-
-
-
-unsigned long gfw(const bitfield_t *);
-
 
 
 #endif  /* _COMMON_BITS_H */
diff --git a/tests/common/bitfield.py b/tests/common/bitfield.py
new file mode 100644
index 0000000..ec61291
--- /dev/null
+++ b/tests/common/bitfield.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+# Tests minimalistes pour valider la construction de chemins relatifs et absolus.
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.common import bitfield
+
+
+class TestBitfields(ChrysalideTestCase):
+    """TestCase for common.bitfield*"""
+
+    def testDuplicateBitfield(self):
+        """Check duplicated bitfield value."""
+
+        bf = bitfield(10, 0)
+
+        bf2 = bf.dup()
+
+        self.assertEqual(bf, bf2)
+
+
+    def testBitfieldValues(self):
+        """Evaluate bitfields basic values."""
+
+        bf_a = bitfield(75, 1)
+
+        bf_b = bitfield(75, 0)
+
+        self.assertNotEqual(bf_a, bf_b)
+
+        bf_a = bitfield(75, 1)
+
+        bf_b = bitfield(75, 0)
+        bf_b.set_all()
+
+        self.assertEqual(bf_a, bf_b)
+
+        bf_a = bitfield(75, 1)
+        bf_a.reset_all()
+
+        bf_b = bitfield(75, 0)
+
+        self.assertEqual(bf_a, bf_b)
+
+
+    def testBitfieldLogicalOperations(self):
+        """Perform logical operations on bitfields."""
+
+        bf_a = bitfield(75, 1)
+
+        bf_b = bitfield(75, 0)
+
+        bf_f = bf_a & bf_b
+
+        self.assertEqual(bf_f, bf_b)
+
+        bf_f = bf_a | bf_b
+
+        self.assertEqual(bf_f, bf_a)
+
+
+    def testBitfieldSwitch(self):
+        """Switch various bits in bitfields."""
+
+        bf_1 = bitfield(75, 1)
+
+        bf_0 = bitfield(75, 0)
+
+        bf_t = bitfield(75, 0)
+
+        for i in range(75):
+            bf_t.set(i, 1)
+
+        self.assertEqual(bf_t, bf_1)
+
+        for i in range(75):
+            bf_t.reset(i, 1)
+
+        self.assertEqual(bf_t, bf_0)
+
+
+    def testBitfieldBits(self):
+        """Test bits in bitfields."""
+
+        bf = bitfield(54, 1)
+
+        self.assertTrue(bf.test(0))
+
+        self.assertTrue(bf.test(53))
+
+        self.assertTrue(bf.test_all(0, 54))
+
+        self.assertFalse(bf.test_none(0, 54))
+
+        bf = bitfield(54, 0)
+
+        self.assertFalse(bf.test(0))
+
+        self.assertFalse(bf.test(53))
+
+        self.assertFalse(bf.test_all(0, 54))
+
+        self.assertTrue(bf.test_none(0, 54))
diff --git a/tests/common/pathname.py b/tests/common/pathname.py
index 5cd238c..3692434 100644
--- a/tests/common/pathname.py
+++ b/tests/common/pathname.py
@@ -9,13 +9,13 @@ from chrysacase import ChrysalideTestCase
 from pychrysalide.common import pathname
 
 
-class TestRestrictedContent(ChrysalideTestCase):
+class TestPathNames(ChrysalideTestCase):
     """TestCase for common.pathname.build*"""
 
     @classmethod
     def setUpClass(cls):
 
-        super(TestRestrictedContent, cls).setUpClass()
+        super(TestPathNames, cls).setUpClass()
 
         cls._tests = [
             {
-- 
cgit v0.11.2-87-g4458