From dff8fd4c83d9833d4539e2dd0c9d3f998b73608f Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 26 Jan 2019 10:19:53 +0100
Subject: Extended the Python API.

---
 plugins/pychrysalide/arch/instruction.c    | 265 ++++++++++++++++++++++-------
 plugins/pychrysalide/arch/operand.c        |  45 +++++
 plugins/pychrysalide/arch/operand.h        |   3 +
 plugins/pychrysalide/glibext/Makefile.am   |   1 +
 plugins/pychrysalide/glibext/buffercache.c |   4 +-
 plugins/pychrysalide/glibext/buffercache.h |   4 +-
 plugins/pychrysalide/glibext/bufferview.c  | 156 +++++++++++++++++
 plugins/pychrysalide/glibext/bufferview.h  |  42 +++++
 plugins/pychrysalide/glibext/module.c      |   2 +
 src/arch/instruction.c                     |  46 ++---
 src/arch/instruction.h                     |  54 +++---
 11 files changed, 502 insertions(+), 120 deletions(-)
 create mode 100644 plugins/pychrysalide/glibext/bufferview.c
 create mode 100644 plugins/pychrysalide/glibext/bufferview.h

diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 881c6ff..fb2df5b 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -35,6 +35,7 @@
 #include <plugins/dt.h>
 
 
+#include "operand.h"
 #include "vmpa.h"
 #include "../access.h"
 #include "../helpers.h"
@@ -105,6 +106,23 @@ static int py_arch_instruction_init(PyObject *, PyObject *, PyObject *);
 
 
 
+/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */
+
+
+/* Attache un opérande supplémentaire à une instruction. */
+static PyObject *py_arch_instruction_attach_extra_operand(PyObject *, PyObject *);
+
+/* Fournit tous les opérandes d'une instruction. */
+static PyObject *py_arch_instruction_get_operands(PyObject *, void *);
+
+/* Remplace un opérande d'une instruction par un autre. */
+static PyObject *py_arch_instruction_replace_operand(PyObject *, PyObject *);
+
+/* Détache un opérande liée d'une instruction. */
+static PyObject *py_arch_instruction_detach_operand(PyObject *, PyObject *);
+
+
+
 /* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
 
 
@@ -131,9 +149,6 @@ static int py_arch_instruction_set_range(PyObject *, PyObject *, void *);
 /* Fournit le nom humain de l'instruction manipulée. */
 static PyObject *py_arch_instruction_get_keyword(PyObject *, void *);
 
-/* Fournit tous les opérandes d'une instruction. */
-static PyObject *py_arch_instruction_get_operands(PyObject *, void *);
-
 /* Définit les constantes pour les instructions. */
 static bool py_arch_instruction_define_constants(PyTypeObject *);
 
@@ -401,6 +416,178 @@ static int py_arch_instruction_init(PyObject *self, PyObject *args, PyObject *kw
 
 
 /* ---------------------------------------------------------------------------------- */
+/*                             MANIPULATION DES OPERANDES                             */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = architecture concernée par la procédure.              *
+*                args = instruction représentant le point de départ.          *
+*                                                                             *
+*  Description : Attache un opérande supplémentaire à une instruction.        *
+*                                                                             *
+*  Retour      : None.                                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_attach_extra_operand(PyObject *self, PyObject *args)
+{
+    GArchOperand *op;                       /* Opérande concerné à ajouter */
+    int ret;                                /* Bilan de lecture des args.  */
+    GArchInstruction *instr;                /* Instruction manipulée       */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &op);
+    if (!ret) return NULL;
+
+    instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+    g_object_ref(G_OBJECT(op));
+
+    g_arch_instruction_attach_extra_operand(instr, op);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self   = objet représentant une instruction.                 *
+*                unused = adresse non utilisée ici.                           *
+*                                                                             *
+*  Description : Fournit tous les opérandes d'une instruction.                *
+*                                                                             *
+*  Retour      : Valeur associée à la propriété consultée.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_get_operands(PyObject *self, void *unused)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    GArchInstruction *instr;                /* Version native              */
+    size_t count;                           /* Nombre d'opérandes présents */
+    size_t i;                               /* Boucle de parcours          */
+    GArchOperand *operand;                  /* Opérande à manipuler        */
+    PyObject *opobj;                        /* Version Python              */
+#ifndef NDEBUG
+    int ret;                                /* Bilan d'une écriture d'arg. */
+#endif
+
+    instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+    g_arch_instruction_lock_operands(instr);
+
+    count = _g_arch_instruction_count_operands(instr);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        operand = _g_arch_instruction_get_operand(instr, i);
+
+        opobj = pygobject_new(G_OBJECT(operand));
+
+#ifndef NDEBUG
+        ret = PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
+        assert(ret == 0);
+#else
+        PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
+#endif
+
+        g_object_unref(G_OBJECT(operand));
+
+    }
+
+    g_arch_instruction_unlock_operands(instr);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = architecture concernée par la procédure.              *
+*                args = instruction représentant le point de départ.          *
+*                                                                             *
+*  Description : Remplace un opérande d'une instruction par un autre.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_replace_operand(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    GArchOperand *old;                      /* Ancien opérande à remplacer */
+    GArchOperand *new;                      /* Nouvel opérande à intégrer  */
+    int ret;                                /* Bilan de lecture des args.  */
+    GArchInstruction *instr;                /* Instruction manipulée       */
+    bool status;                            /* Bilan de l'opération        */
+
+    ret = PyArg_ParseTuple(args, "O&O&", convert_to_arch_operand, &old, convert_to_arch_operand, &new);
+    if (!ret) return NULL;
+
+    instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+    status = g_arch_instruction_replace_operand(instr, old, new);
+
+    if (status)
+        g_object_ref(G_OBJECT(new));
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = architecture concernée par la procédure.              *
+*                args = instruction représentant le point de départ.          *
+*                                                                             *
+*  Description : Détache un opérande liée d'une instruction.                  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_detach_operand(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    GArchOperand *target;                   /* Opérande ciblé par l'action */
+    int ret;                                /* Bilan de lecture des args.  */
+    GArchInstruction *instr;                /* Instruction manipulée       */
+    bool status;                            /* Bilan de l'opération        */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target);
+    if (!ret) return NULL;
+
+    instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+    status = g_arch_instruction_detach_operand(instr, target);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
 /*                     DEFINITION DES LIAISONS ENTRE INSTRUCTIONS                     */
 /* ---------------------------------------------------------------------------------- */
 
@@ -652,63 +839,6 @@ static PyObject *py_arch_instruction_get_keyword(PyObject *self, void *unused)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self   = objet représentant une instruction.                 *
-*                unused = adresse non utilisée ici.                           *
-*                                                                             *
-*  Description : Fournit tous les opérandes d'une instruction.                *
-*                                                                             *
-*  Retour      : Valeur associée à la propriété consultée.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_arch_instruction_get_operands(PyObject *self, void *unused)
-{
-    PyObject *result;                       /* Instance à retourner        */
-    GArchInstruction *instr;                /* Version native              */
-    size_t count;                           /* Nombre d'opérandes présents */
-    size_t i;                               /* Boucle de parcours          */
-    GArchOperand *operand;                  /* Opérande à manipuler        */
-    PyObject *opobj;                        /* Version Python              */
-#ifndef NDEBUG
-    int ret;                                /* Bilan d'une écriture d'arg. */
-#endif
-
-    instr = G_ARCH_INSTRUCTION(pygobject_get(self));
-
-    g_arch_instruction_lock_operands(instr);
-
-    count = _g_arch_instruction_count_operands(instr);
-
-    result = PyTuple_New(count);
-
-    for (i = 0; i < count; i++)
-    {
-        operand = _g_arch_instruction_get_operand(instr, i);
-
-        opobj = pygobject_new(G_OBJECT(operand));
-
-#ifndef NDEBUG
-        ret = PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
-        assert(ret == 0);
-#else
-        PyTuple_SetItem(result, i, Py_BuildValue("O", opobj));
-#endif
-
-        g_object_unref(G_OBJECT(operand));
-
-    }
-
-    g_arch_instruction_unlock_operands(instr);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
 *                                                                             *
 *  Description : Définit les constantes pour les instructions.                *
@@ -755,6 +885,21 @@ static bool py_arch_instruction_define_constants(PyTypeObject *obj_type)
 PyTypeObject *get_python_arch_instruction_type(void)
 {
     static PyMethodDef py_arch_instruction_methods[] = {
+        {
+            "attach_operand", py_arch_instruction_attach_extra_operand,
+            METH_VARARGS,
+            "attach_operand($self, op, /)\n--\n\nAdd a new operand to the instruction."
+        },
+        {
+            "replace_operand", py_arch_instruction_replace_operand,
+            METH_VARARGS,
+            "replace_operand($self, old, new, /)\n--\n\nReplace an old instruction operand by a another one."
+        },
+        {
+            "detach_operand", py_arch_instruction_detach_operand,
+            METH_VARARGS,
+            "detach_operand($self, target, /)\n--\n\nRemove an operand from the instruction."
+        },
         { NULL }
     };
 
diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c
index 4630b3a..6780e10 100644
--- a/plugins/pychrysalide/arch/operand.c
+++ b/plugins/pychrysalide/arch/operand.c
@@ -223,3 +223,48 @@ bool ensure_python_arch_operand_is_registered(void)
     return true;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en opérande d'architecture.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_arch_operand(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_arch_operand_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to arch operand");
+            break;
+
+        case 1:
+            *((GArchOperand **)dst) = G_ARCH_OPERAND(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/arch/operand.h b/plugins/pychrysalide/arch/operand.h
index a718d8f..595a4fc 100644
--- a/plugins/pychrysalide/arch/operand.h
+++ b/plugins/pychrysalide/arch/operand.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_arch_operand_type(void);
 /* Prend en charge l'objet 'pychrysalide.arch.ArchOperand'. */
 bool ensure_python_arch_operand_is_registered(void);
 
+/* Tente de convertir en opérande d'architecture. */
+int convert_to_arch_operand(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERAND_H */
diff --git a/plugins/pychrysalide/glibext/Makefile.am b/plugins/pychrysalide/glibext/Makefile.am
index c09f4fa..086ca28 100644
--- a/plugins/pychrysalide/glibext/Makefile.am
+++ b/plugins/pychrysalide/glibext/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libpychrysaglibext.la
 libpychrysaglibext_la_SOURCES =			\
 	buffercache.h buffercache.c			\
 	bufferline.h bufferline.c			\
+	bufferview.h bufferview.c			\
 	configuration.h configuration.c		\
 	linecursor.h linecursor.c			\
 	linegen.h linegen.c					\
diff --git a/plugins/pychrysalide/glibext/buffercache.c b/plugins/pychrysalide/glibext/buffercache.c
index 8818f5e..6f07f4e 100644
--- a/plugins/pychrysalide/glibext/buffercache.c
+++ b/plugins/pychrysalide/glibext/buffercache.c
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * buffercache.c - équivalent Python du fichier "glibext/gbuffercache.h"
+ * buffercache.c - équivalent Python du fichier "glibext/gbuffercache.c"
  *
  * Copyright (C) 2016-2017 Cyrille Bagard
  *
@@ -120,7 +120,7 @@ PyTypeObject *get_python_buffer_cache_type(void)
 
         PyVarObject_HEAD_INIT(NULL, 0)
 
-        .tp_name        = "pychrysalide.glibext.Buffercache",
+        .tp_name        = "pychrysalide.glibext.BufferCache",
         .tp_basicsize   = sizeof(PyGObject),
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
diff --git a/plugins/pychrysalide/glibext/buffercache.h b/plugins/pychrysalide/glibext/buffercache.h
index 728acd7..c0e4493 100644
--- a/plugins/pychrysalide/glibext/buffercache.h
+++ b/plugins/pychrysalide/glibext/buffercache.h
@@ -1,6 +1,6 @@
 
 /* Chrysalide - Outil d'analyse de fichiers binaires
- * buffercache.h - prototypes pour l'équivalent Python du fichier "glibext/buffercache.h"
+ * buffercache.h - prototypes pour l'équivalent Python du fichier "glibext/gbuffercache.h"
  *
  * Copyright (C) 2016-2017 Cyrille Bagard
  *
@@ -34,7 +34,7 @@
 /* Fournit un accès à une définition de type à diffuser. */
 PyTypeObject *get_python_buffer_cache_type(void);
 
-/* Prend en charge l'objet 'pychrysalide.glibext.CodeBuffer'. */
+/* Prend en charge l'objet 'pychrysalide.glibext.BufferCache'. */
 bool ensure_python_buffer_cache_is_registered(void);
 
 
diff --git a/plugins/pychrysalide/glibext/bufferview.c b/plugins/pychrysalide/glibext/bufferview.c
new file mode 100644
index 0000000..1c8d7cc
--- /dev/null
+++ b/plugins/pychrysalide/glibext/bufferview.c
@@ -0,0 +1,156 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bufferview.c - équivalent Python du fichier "glibext/gbufferview.c"
+ *
+ * Copyright (C) 2018 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 "bufferview.h"
+
+
+#include <pygobject.h>
+
+
+#include <glibext/gbufferview.h>
+
+
+#include "../access.h"
+#include "../helpers.h"
+
+
+
+/* Fournit le tampon de code lié à un visualisateur donné. */
+static PyObject *py_buffer_view_get_cache(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le tampon de code lié à un visualisateur donné.      *
+*                                                                             *
+*  Retour      : Tampon de code associé au gestionnaire d'affichage.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_buffer_view_get_cache(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GBufferView *view;                      /* Vue GLib à consulter        */
+    GBufferCache *cache;                    /* Tampon associé à cette vue  */
+
+    view = G_BUFFER_VIEW(pygobject_get(self));
+
+    cache = g_buffer_view_get_cache(view);
+
+    result = pygobject_new(G_OBJECT(cache));
+
+    g_object_unref(G_OBJECT(cache));
+
+    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_buffer_view_type(void)
+{
+    static PyMethodDef py_buffer_view_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_buffer_view_getseters[] = {
+        {
+            "cache", py_buffer_view_get_cache, NULL,
+            "Provide the buffer cache for the view.", NULL
+        },
+        { NULL }
+    };
+
+    static PyTypeObject py_buffer_view_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.glibext.BufferView",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = "PyChrysalide code buffer",
+
+        .tp_methods     = py_buffer_view_methods,
+        .tp_getset      = py_buffer_view_getseters,
+
+    };
+
+    return &py_buffer_view_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.glibext.BufferView'.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_buffer_view_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'BufferView'    */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_buffer_view_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.glibext");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_VIEW, type, &PyGObject_Type))
+            return false;
+
+    }
+
+    return true;
+
+}
diff --git a/plugins/pychrysalide/glibext/bufferview.h b/plugins/pychrysalide/glibext/bufferview.h
new file mode 100644
index 0000000..2ac08b9
--- /dev/null
+++ b/plugins/pychrysalide/glibext/bufferview.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bufferview.h - prototypes pour l'équivalent Python du fichier "glibext/gbufferview.h"
+ *
+ * Copyright (C) 2018 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_PYCHRYSALIDE_GLIBEXT_BUFFERVIEW_H
+#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_BUFFERVIEW_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_buffer_view_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.glibext.BufferView'. */
+bool ensure_python_buffer_view_is_registered(void);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_BUFFERVIEW_H */
diff --git a/plugins/pychrysalide/glibext/module.c b/plugins/pychrysalide/glibext/module.c
index 2429dbd..f1c0bbb 100644
--- a/plugins/pychrysalide/glibext/module.c
+++ b/plugins/pychrysalide/glibext/module.c
@@ -30,6 +30,7 @@
 
 #include "buffercache.h"
 #include "bufferline.h"
+#include "bufferview.h"
 #include "configuration.h"
 #include "linecursor.h"
 #include "linegen.h"
@@ -95,6 +96,7 @@ bool populate_glibext_module(void)
 
     if (result) result = ensure_python_buffer_cache_is_registered();
     if (result) result = ensure_python_buffer_line_is_registered();
+    if (result) result = ensure_python_buffer_view_is_registered();
     if (result) result = ensure_python_config_param_is_registered();
     if (result) result = ensure_python_config_param_iterator_is_registered();
     if (result) result = ensure_python_generic_config_is_registered();
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 5ce0c12..1d1ccaf 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -585,35 +585,6 @@ GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, siz
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr = instance à mettre à jour.                            *
-*                old   = ancien opérande à remplacer.                         *
-*                new   = nouvel opérande à intégrer.                          *
-*                                                                             *
-*  Description : Remplace un opérande d'une instruction par un autre.         *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    g_arch_instruction_lock_operands(instr);
-
-    result = _g_arch_instruction_replace_operand(instr, old, new);
-
-    g_arch_instruction_unlock_operands(instr);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : instr = instance à mettre à jour.                            *
 *                old   = ancienne opérande à détacher.                        *
 *                new   = nouvelle opérande à attacher.                        *
 *                                                                             *
@@ -670,14 +641,15 @@ bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *
 *                                                                             *
 *  Description : Détache un opérande liée d'une instruction.                  *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
+bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
 {
+    bool result;                            /* Bilan à retourner           */
     size_t count;                           /* Nombre d'opérandes en place */
     size_t i;                               /* Boucle de parcours          */
     GArchOperand *op;                       /* Opérande à manipuler        */
@@ -695,9 +667,17 @@ void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
 
     }
 
-    rem_item_from_flat_array(&instr->operands, i, sizeof(GArchOperand *));
+    result = (i < count);
+
+    if (result)
+    {
+        rem_item_from_flat_array(&instr->operands, i, sizeof(GArchOperand *));
+
+        g_object_unref(G_OBJECT(target));
+
+    }
 
-    g_object_unref(G_OBJECT(target));
+    return result;
 
 }
 
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 8289a43..217e38b 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -148,38 +148,46 @@ size_t _g_arch_instruction_count_operands(const GArchInstruction *);
 GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t);
 
 /* Remplace un opérande d'une instruction par un autre. */
-bool g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
-
-/* Remplace un opérande d'une instruction par un autre. */
 bool _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
 
 /* Détache un opérande liée d'une instruction. */
-void _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
+bool _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
 
 
-#define g_arch_instruction_count_operands(ins)                  \
-    ({                                                          \
-        size_t __result;                                        \
-        g_arch_instruction_lock_operands(ins);                  \
-        __result = _g_arch_instruction_count_operands(ins);     \
-        g_arch_instruction_unlock_operands(ins);                \
-        __result;                                               \
+#define g_arch_instruction_count_operands(ins)                      \
+    ({                                                              \
+        size_t __result;                                            \
+        g_arch_instruction_lock_operands(ins);                      \
+        __result = _g_arch_instruction_count_operands(ins);         \
+        g_arch_instruction_unlock_operands(ins);                    \
+        __result;                                                   \
+    })
+
+#define g_arch_instruction_get_operand(ins, idx)                    \
+    ({                                                              \
+        GArchOperand *__result;                                     \
+        g_arch_instruction_lock_operands(ins);                      \
+        __result = _g_arch_instruction_get_operand(ins, idx);       \
+        g_arch_instruction_unlock_operands(ins);                    \
+        __result;                                                   \
     })
 
-#define g_arch_instruction_get_operand(ins, idx)                \
-    ({                                                          \
-        GArchOperand *__result;                                 \
-        g_arch_instruction_lock_operands(ins);                  \
-        __result = _g_arch_instruction_get_operand(ins, idx);   \
-        g_arch_instruction_unlock_operands(ins);                \
-        __result;                                               \
+#define g_arch_instruction_replace_operand(ins, o, n)               \
+    ({                                                              \
+        bool __result;                                              \
+        g_arch_instruction_lock_operands(ins);                      \
+        __result = _g_arch_instruction_replace_operand(ins, o, n);  \
+        g_arch_instruction_unlock_operands(ins);                    \
+        __result;                                                   \
     })
 
-#define g_arch_instruction_detach_operand(ins, o)               \
-    ({                                                          \
-        g_arch_instruction_lock_operands(ins);                  \
-        _g_arch_instruction_detach_operand(ins, o);             \
-        g_arch_instruction_unlock_operands(ins);                \
+#define g_arch_instruction_detach_operand(ins, o)                   \
+    ({                                                              \
+        bool __result;                                              \
+        g_arch_instruction_lock_operands(ins);                      \
+        __result = _g_arch_instruction_detach_operand(ins, o);      \
+        g_arch_instruction_unlock_operands(ins);                    \
+        __result;                                                   \
     })
 
 
-- 
cgit v0.11.2-87-g4458