From 32bef30025f5e3f513c2b4936c0573cc3b629961 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 8 Feb 2019 00:42:02 +0100
Subject: Rewritten some Python instance allocation functions.

---
 plugins/pychrysalide/arch/instriter.c |  43 +-------------
 plugins/pychrysalide/arch/vmpa.c      | 104 ++++++++++++++++++++--------------
 plugins/pychrysalide/common/bits.c    |  81 ++++++++++++++++++++------
 plugins/pychrysalide/format/symiter.c |  43 +-------------
 4 files changed, 125 insertions(+), 146 deletions(-)

diff --git a/plugins/pychrysalide/arch/instriter.c b/plugins/pychrysalide/arch/instriter.c
index 9b149fd..bb1e1a3 100644
--- a/plugins/pychrysalide/arch/instriter.c
+++ b/plugins/pychrysalide/arch/instriter.c
@@ -57,9 +57,6 @@ static PyObject *py_instr_iterator_next(PyInstrIterator *);
 /* Initialise un nouvel itérateur. */
 static int py_instr_iterator_init(PyInstrIterator *, PyObject *, PyObject *);
 
-/* Construit un nouvel itérateur. */
-static PyObject *py_instr_iterator_new(PyTypeObject *, PyObject *, PyObject *);
-
 
 
 /******************************************************************************
@@ -172,44 +169,6 @@ static int py_instr_iterator_init(PyInstrIterator *self, PyObject *args, PyObjec
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type d'objet à mettre en place.                       *
-*                args = arguments passés pour l'appel.                        *
-*                kwds = mots clefs éventuellement fournis en complément.      *
-*                                                                             *
-*  Description : Construit un nouvel itérateur.                               *
-*                                                                             *
-*  Retour      : Définition d'objet pour Python.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_instr_iterator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyInstrIterator *result;                /* Nouvelle instance à renvoyer*/
-    int ret;                                /* Bilan de l'initialisation   */
-
-    result = (PyInstrIterator *)type->tp_alloc(type, 0);
-
-    if (result != NULL)
-    {
-        ret = py_instr_iterator_init(result, args, kwds);
-
-        if (ret != 0)
-        {
-            Py_DECREF(result);
-            result = NULL;
-        }
-
-    }
-
-    return (PyObject *)result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -239,7 +198,7 @@ PyTypeObject *get_python_instr_iterator_type(void)
         .tp_iternext    = (iternextfunc)py_instr_iterator_next,
 
         .tp_init        = (initproc)py_instr_iterator_init,
-        .tp_new         = py_instr_iterator_new,
+        .tp_new         = PyType_GenericNew,
 
     };
 
diff --git a/plugins/pychrysalide/arch/vmpa.c b/plugins/pychrysalide/arch/vmpa.c
index 0474fe0..b042a9f 100644
--- a/plugins/pychrysalide/arch/vmpa.c
+++ b/plugins/pychrysalide/arch/vmpa.c
@@ -70,8 +70,8 @@ static PyObject *py_vmpa_get_value(PyObject *, void *);
 /* Définit une partie du contenu de la position représentée. */
 static int py_vmpa_set_value(PyObject *, PyObject *, void *);
 
-/* Crée un nouvel objet Python de type 'vmpa2t'. */
-static PyObject *py_vmpa_new(PyTypeObject *, PyObject *, PyObject *);
+/* Initialise un objet Python de type 'vmpa2t'. */
+static int py_vmpa_init(py_vmpa_t *, PyObject *, PyObject *);
 
 /* Effectue une conversion d'un objet Python en type 'vmpa_t'. */
 static bool convert_pyobj_to_vmpa(PyObject *, vmpa2t *);
@@ -130,9 +130,8 @@ static PyObject *py_mrange_get_end_addr(PyObject *, void *);
 
 
 
-
-/* Crée un nouvel objet Python de type 'mrange'. */
-static PyObject *py_mrange_new(PyTypeObject *, PyObject *, PyObject *);
+/* Initialise un objet Python de type 'mrange_t'. */
+static int py_mrange_init(py_mrange_t *, PyObject *, PyObject *);
 
 
 
@@ -380,40 +379,42 @@ static int py_vmpa_set_value(PyObject *self, PyObject *value, void *closure)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type de l'objet à instancier.                         *
-*                args = arguments fournis à l'appel.                          *
-*                kwds = arguments de type key=val fournis.                    *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
 *                                                                             *
-*  Description : Crée un nouvel objet Python de type 'vmpa2t'.                *
+*  Description : Initialise un objet Python de type 'vmpa2t'.                 *
 *                                                                             *
-*  Retour      : Instance Python mise en place.                               *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_vmpa_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_vmpa_init(py_vmpa_t *self, PyObject *args, PyObject *kwds)
 {
-    py_vmpa_t *result;                      /* Instance à retourner        */
+    int result;                             /* Bilan à retourner           */
     unsigned long long phy;                 /* Position physique           */
     unsigned long long virt;                /* Adresse en mémoire virtuelle*/
     int ret;                                /* Bilan de lecture des args.  */
 
+    result = -1;
+
     phy = VMPA_NO_PHYSICAL;
     virt = VMPA_NO_VIRTUAL;
 
     ret = PyArg_ParseTuple(args, "|KK", &phy, &virt);
-    if (!ret) return NULL;
-
-    result = (py_vmpa_t *)type->tp_alloc(type, 0);
+    if (!ret) goto exit;
 
-    init_vmpa(&result->addr, phy, virt);
+    init_vmpa(&self->addr, phy, virt);
 
-    return (PyObject *)result;
+    result = 0;
 
-}
+ exit:
 
+    return result;
 
+}
 
 
 
@@ -637,7 +638,9 @@ PyTypeObject *get_python_vmpa_type(void)
         .tp_richcompare = py_vmpa_richcompare,
 
         .tp_getset      = py_vmpa_getseters,
-        .tp_new         = py_vmpa_new
+
+        .tp_init        = (initproc)py_vmpa_init,
+        .tp_new         = PyType_GenericNew,
 
     };
 
@@ -723,16 +726,19 @@ vmpa2t *get_internal_vmpa(PyObject *obj)
 
 PyObject *build_from_internal_vmpa(const vmpa2t *addr)
 {
-    py_vmpa_t *result;                      /* Instance à retourner        */
+    PyObject *result;                       /* Instance à retourner        */
     PyTypeObject *type;                     /* Type à instancier           */
+    PyObject *args;                         /* Liste des arguments d'appel */
 
     type = get_python_vmpa_type();
 
-    result = (py_vmpa_t *)type->tp_alloc(type, 0);
+    args = Py_BuildValue("KK", get_phy_addr(addr), get_virt_addr(addr));
 
-    copy_vmpa(&result->addr, addr);
+    result = PyObject_CallObject((PyObject *)type, args);
 
-    return (PyObject *)result;
+    Py_DECREF(args);
+
+    return result;
 
 }
 
@@ -1122,45 +1128,46 @@ static PyObject *py_mrange_get_end_addr(PyObject *self, void *closure)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type de l'objet à instancier.                         *
-*                args = arguments fournis à l'appel.                          *
-*                kwds = arguments de type key=val fournis.                    *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
 *                                                                             *
-*  Description : Crée un nouvel objet Python de type 'mrange'.                *
+*  Description : Initialise un objet Python de type 'mrange_t'.               *
 *                                                                             *
-*  Retour      : Instance Python mise en place.                               *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_mrange_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_mrange_init(py_mrange_t *self, PyObject *args, PyObject *kwds)
 {
-    py_mrange_t *result;                    /* Instance à retourner        */
+    int result;                             /* Bilan à retourner           */
     PyObject *py_vmpa;                      /* Localisation version Python */
     unsigned long long length;              /* Taille physique             */
     int ret;                                /* Bilan de lecture des args.  */
     vmpa2t *addr;                           /* Localisation version C      */
 
+    result = -1;
+
     ret = PyArg_ParseTuple(args, "OK", &py_vmpa, &length);
-    if (!ret) return NULL;
+    if (!ret) goto exit;
 
     ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type());
-    if (!ret) return NULL;
+    if (!ret) goto exit;
 
     addr = get_internal_vmpa(py_vmpa);
-    if (addr == NULL) return NULL;
+    if (addr == NULL) goto exit;
 
-    result = (py_mrange_t *)type->tp_alloc(type, 0);
+    init_mrange(&self->range, addr, length);
 
-    init_mrange(&result->range, addr, length);
-
-    return (PyObject *)result;
-
-}
+    result = 0;
 
+ exit:
 
+    return result;
 
+}
 
 
 
@@ -1231,7 +1238,9 @@ PyTypeObject *get_python_mrange_type(void)
 
         .tp_methods     = py_mrange_methods,
         .tp_getset      = py_mrange_getseters,
-        .tp_new         = py_mrange_new
+
+        .tp_init        = (initproc)py_mrange_init,
+        .tp_new         = PyType_GenericNew,
 
     };
 
@@ -1314,15 +1323,22 @@ mrange_t *get_internal_mrange(PyObject *obj)
 
 PyObject *build_from_internal_mrange(const mrange_t *range)
 {
-    py_mrange_t *result;                    /* Instance à retourner        */
+    PyObject *result;                       /* Instance à retourner        */
     PyTypeObject *type;                     /* Type à instancier           */
+    PyObject *addr_obj;                     /* Objet pour l'adresse de base*/
+    PyObject *args;                         /* Liste des arguments d'appel */
 
     type = get_python_mrange_type();
 
-    result = (py_mrange_t *)type->tp_alloc(type, 0);
+    addr_obj = build_from_internal_vmpa(get_mrange_addr(range));
 
-    copy_mrange(&result->range, range);
+    args = Py_BuildValue("OK", addr_obj, get_mrange_length(range));
 
-    return (PyObject *)result;
+    result = PyObject_CallObject((PyObject *)type, args);
+
+    Py_DECREF(args);
+    Py_DECREF(addr_obj);
+
+    return result;
 
 }
diff --git a/plugins/pychrysalide/common/bits.c b/plugins/pychrysalide/common/bits.c
index 7a6454d..c3bacd4 100644
--- a/plugins/pychrysalide/common/bits.c
+++ b/plugins/pychrysalide/common/bits.c
@@ -41,8 +41,11 @@ typedef struct _py_bitfield_t
 
 
 
-/* Crée un nouvel objet Python de type 'bitfield_t'. */
-static PyObject *py_bitfield_new(PyTypeObject *, PyObject *, PyObject *);
+/* Libère de la mémoire un objet Python de type 'bitfield_t'. */
+static void py_bitfield_dealloc(py_bitfield_t *);
+
+/* Initialise un objet Python de type 'bitfield_t'. */
+static int py_bitfield_init(py_bitfield_t *, PyObject *, PyObject *);
 
 /* Crée une copie d'un champ de bits classique. */
 static PyObject *py_bitfield_dup(PyObject *, PyObject *);
@@ -93,33 +96,58 @@ static PyObject *py_bitfield_popcount(PyObject *, void *);
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type de l'objet à instancier.                         *
-*                args = arguments fournis à l'appel.                          *
-*                kwds = arguments de type key=val fournis.                    *
+*  Paramètres  : self = champ de bits à supprimer.                            *
+*                                                                             *
+*  Description : Libère de la mémoire un objet Python de type 'bitfield_t'.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_bitfield_dealloc(py_bitfield_t *self)
+{
+    delete_bit_field(self->native);
+
+    Py_TYPE(self)->tp_free((PyObject *)self);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
 *                                                                             *
-*  Description : Crée un nouvel objet Python de type 'bitfield_t'.            *
+*  Description : Initialise un objet Python de type 'bitfield_t'.             *
 *                                                                             *
-*  Retour      : Instance Python mise en place.                               *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_bitfield_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_bitfield_init(py_bitfield_t *self, PyObject *args, PyObject *kwds)
 {
-    py_bitfield_t *result;                  /* Instance à retourner        */
+    int result;                             /* Bilan à retourner           */
     unsigned long length;                   /* Taille du champ à créer     */
     int state;                              /* Initialisation par défaut   */
     int ret;                                /* Bilan de lecture des args.  */
 
+    result = -1;
+
     ret = PyArg_ParseTuple(args, "kp", &length, &state);
-    if (!ret) return NULL;
+    if (ret == 0) goto exit;
+
+    self->native = create_bit_field(length, state);
 
-    result = (py_bitfield_t *)type->tp_alloc(type, 0);
+    result = 0;
 
-    result->native = create_bit_field(length, state);
+ exit:
 
-    return (PyObject *)result;
+    return result;
 
 }
 
@@ -726,6 +754,8 @@ PyTypeObject *get_python_bitfield_type(void)
         .tp_name        = "pychrysalide.common.bitfield",
         .tp_basicsize   = sizeof(py_bitfield_t),
 
+        .tp_dealloc     = (destructor)py_bitfield_dealloc,
+
         .tp_as_number   = &py_bitfield_nb_proto,
         .tp_as_sequence = &py_bitfield_sequence_proto,
 
@@ -737,7 +767,9 @@ PyTypeObject *get_python_bitfield_type(void)
 
         .tp_methods     = py_bitfield_methods,
         .tp_getset      = py_bitfield_getseters,
-        .tp_new         = py_bitfield_new
+
+        .tp_init        = (initproc)py_bitfield_init,
+        .tp_new         = PyType_GenericNew,
 
     };
 
@@ -796,15 +828,28 @@ bool ensure_python_bitfield_is_registered(void)
 
 PyObject *build_from_internal_bitfield(const bitfield_t *field)
 {
-    py_bitfield_t *result;                  /* Instance à retourner        */
+    PyObject *result;                       /* Instance à retourner        */
     PyTypeObject *type;                     /* Type à instancier           */
+    PyObject *args;                         /* Liste des arguments d'appel */
+    py_bitfield_t *bf_obj;                  /* Objet précis instancié      */
 
     type = get_python_bitfield_type();
 
-    result = (py_bitfield_t *)type->tp_alloc(type, 0);
+    /**
+     * Le format "p" n'existe pas pour Py_BuildValue().
+     */
+    args = Py_BuildValue("kk", 0, 0);
+
+    result = PyObject_CallObject((PyObject *)type, args);
+
+    Py_DECREF(args);
 
-    result->native = dup_bit_field(field);
+    bf_obj = (py_bitfield_t *)result;
 
-    return (PyObject *)result;
+    delete_bit_field(bf_obj->native);
+
+    bf_obj->native = dup_bit_field(field);
+
+    return result;
 
 }
diff --git a/plugins/pychrysalide/format/symiter.c b/plugins/pychrysalide/format/symiter.c
index 03a0ec8..8deabe9 100644
--- a/plugins/pychrysalide/format/symiter.c
+++ b/plugins/pychrysalide/format/symiter.c
@@ -57,9 +57,6 @@ static PyObject *py_sym_iterator_next(PySymIterator *);
 /* Initialise un nouvel itérateur. */
 static int py_sym_iterator_init(PySymIterator *, PyObject *, PyObject *);
 
-/* Construit un nouvel itérateur. */
-static PyObject *py_sym_iterator_new(PyTypeObject *, PyObject *, PyObject *);
-
 
 
 /******************************************************************************
@@ -172,44 +169,6 @@ static int py_sym_iterator_init(PySymIterator *self, PyObject *args, PyObject *k
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type d'objet à mettre en place.                       *
-*                args = arguments passés pour l'appel.                        *
-*                kwds = mots clefs éventuellement fournis en complément.      *
-*                                                                             *
-*  Description : Construit un nouvel itérateur.                               *
-*                                                                             *
-*  Retour      : Définition d'objet pour Python.                              *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_sym_iterator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PySymIterator *result;                  /* Nouvelle instance à renvoyer*/
-    int ret;                                /* Bilan de l'initialisation   */
-
-    result = (PySymIterator *)type->tp_alloc(type, 0);
-
-    if (result != NULL)
-    {
-        ret = py_sym_iterator_init(result, args, kwds);
-
-        if (ret != 0)
-        {
-            Py_DECREF(result);
-            result = NULL;
-        }
-
-    }
-
-    return (PyObject *)result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -239,7 +198,7 @@ PyTypeObject *get_python_sym_iterator_type(void)
         .tp_iternext    = (iternextfunc)py_sym_iterator_next,
 
         .tp_init        = (initproc)py_sym_iterator_init,
-        .tp_new         = py_sym_iterator_new,
+        .tp_new         = PyType_GenericNew,
 
     };
 
-- 
cgit v0.11.2-87-g4458