From 6ba868e1b5961cec8db21adabf36027f97205f0f Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 25 Sep 2020 15:40:18 +0200
Subject: Provided as much information as possible for instruction links in
 Python.

---
 plugins/pychrysalide/analysis/block.c   | 83 ++++++++++++++++++++++-----------
 plugins/pychrysalide/arch/instruction.c | 40 +++++++++++-----
 2 files changed, 85 insertions(+), 38 deletions(-)

diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c
index 3d51676..0b09eb7 100644
--- a/plugins/pychrysalide/analysis/block.c
+++ b/plugins/pychrysalide/analysis/block.c
@@ -34,6 +34,7 @@
 
 #include "../access.h"
 #include "../helpers.h"
+#include "../arch/instruction.h"
 #include "../arch/vmpa.h"
 
 
@@ -154,8 +155,22 @@ static PyObject *py_code_block_get_sources(PyObject *self, void *closure)
     size_t count;                           /* Quantité de blocs liés      */
     block_link_t *links;                    /* Liens à traiter             */
     size_t i;                               /* Boucle de parcours          */
-    block_link_t *link;                     /* Informations conservées     */
-    PyObject *info;                         /* Informations à transmettre  */
+    block_link_t *source;                   /* Origine des liens           */
+    PyObject *linked;                       /* Source de lien Python       */
+    PyObject *type;                         /* Nature du lien en Python    */
+#ifndef NDEBUG
+    int ret;                                /* Bilan d'une écriture d'arg. */
+#endif
+
+#define CODE_BLOCK_SOURCES_ATTRIB PYTHON_GET_DEF_FULL               \
+(                                                                   \
+    sources, py_code_block,                                         \
+    "List of source blocks.\n"                                      \
+    "\n"                                                            \
+    "Each item of the resulting tuple is a pair of"                 \
+    " pychrysalide.analysis.CodeBlock instance and"                 \
+    " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \
+)
 
     block = G_CODE_BLOCK(pygobject_get(self));
 
@@ -165,16 +180,20 @@ static PyObject *py_code_block_get_sources(PyObject *self, void *closure)
 
     for (i = 0; i < count; i++)
     {
-        link = &links[i];
+        source = &links[i];
 
-        info = PyTuple_New(2);
+        linked = pygobject_new(G_OBJECT(source->linked));
+        type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
+                                                   "InstructionLinkType", source->type);
 
-        PyTuple_SetItem(info, 0, pygobject_new(G_OBJECT(link->linked)));
-        PyTuple_SetItem(info, 1, PyLong_FromUnsignedLong(link->type));
+#ifndef NDEBUG
+        ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
+        assert(ret == 0);
+#else
+        PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
+#endif
 
-        PyTuple_SetItem(result, i, info);
-
-        unref_block_link(link);
+        unref_block_link(source);
 
     }
 
@@ -206,8 +225,22 @@ static PyObject *py_code_block_get_destinations(PyObject *self, void *closure)
     size_t count;                           /* Quantité de blocs liés      */
     block_link_t *links;                    /* Liens à traiter             */
     size_t i;                               /* Boucle de parcours          */
-    block_link_t *link;                     /* Informations conservées     */
-    PyObject *info;                         /* Informations à transmettre  */
+    block_link_t *dest;                     /* Destination des liens       */
+    PyObject *linked;                       /* Destination de lien Python  */
+    PyObject *type;                         /* Nature du lien en Python    */
+#ifndef NDEBUG
+    int ret;                                /* Bilan d'une écriture d'arg. */
+#endif
+
+#define CODE_BLOCK_DESTINATIONS_ATTRIB PYTHON_GET_DEF_FULL          \
+(                                                                   \
+    destinations, py_code_block,                                    \
+    "List of destination blocks.\n"                                 \
+    "\n"                                                            \
+    "Each item of the resulting tuple is a pair of"                 \
+    " pychrysalide.analysis.CodeBlock instance and"                 \
+    " pychrysalide.arch.ArchInstruction.InstructionLinkType value." \
+)
 
     block = G_CODE_BLOCK(pygobject_get(self));
 
@@ -217,16 +250,20 @@ static PyObject *py_code_block_get_destinations(PyObject *self, void *closure)
 
     for (i = 0; i < count; i++)
     {
-        link = &links[i];
-
-        info = PyTuple_New(2);
+        dest = &links[i];
 
-        PyTuple_SetItem(info, 0, pygobject_new(G_OBJECT(link->linked)));
-        PyTuple_SetItem(info, 1, PyLong_FromUnsignedLong(link->type));
+        linked = pygobject_new(G_OBJECT(dest->linked));
+        type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
+                                                   "InstructionLinkType", dest->type);
 
-        PyTuple_SetItem(result, i, info);
+#ifndef NDEBUG
+        ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
+        assert(ret == 0);
+#else
+        PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
+#endif
 
-        unref_block_link(link);
+        unref_block_link(dest);
 
     }
 
@@ -265,14 +302,8 @@ PyTypeObject *get_python_code_block_type(void)
             "rank", py_code_block_get_rank, NULL,
             "Rang of the code block.", NULL
         },
-        {
-            "sources", py_code_block_get_sources, NULL,
-            "List of source blocks.", NULL
-        },
-        {
-            "destinations", py_code_block_get_destinations, NULL,
-            "List of destination blocks.", NULL
-        },
+        CODE_BLOCK_SOURCES_ATTRIB,
+        CODE_BLOCK_DESTINATIONS_ATTRIB,
         { NULL }
     };
 
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index fcd0c83..3606cfe 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -725,15 +725,25 @@ static PyObject *py_arch_instruction_get_sources(PyObject *self, void *unused)
 {
     PyObject *result;                       /* Instance à retourner        */
     GArchInstruction *instr;                /* Version native              */
-    const instr_link_t *source;             /* Origine des liens           */
     size_t count;                           /* Nombre de liens présents    */
     size_t i;                               /* Boucle de parcours          */
+    const instr_link_t *source;             /* Origine des liens           */
     PyObject *linked;                       /* Source de lien Python       */
     PyObject *type;                         /* Nature du lien en Python    */
 #ifndef NDEBUG
     int ret;                                /* Bilan d'une écriture d'arg. */
 #endif
 
+#define ARCH_INSTRUCTION_SOURCES_ATTRIB PYTHON_GET_DEF_FULL                 \
+(                                                                           \
+    sources, py_arch_instruction,                                           \
+    "Provide the instructions list driving to the current instruction.\n"   \
+    "\n"                                                                    \
+    "Each item of the resulting tuple is a pair of"                         \
+    " pychrysalide.arch.ArchInstruction instance and"                       \
+    " pychrysalide.arch.ArchInstruction.InstructionLinkType value."         \
+)
+
     instr = G_ARCH_INSTRUCTION(pygobject_get(self));
 
     g_arch_instruction_lock_src(instr);
@@ -747,7 +757,8 @@ static PyObject *py_arch_instruction_get_sources(PyObject *self, void *unused)
         source = g_arch_instruction_get_source(instr, i);
 
         linked = pygobject_new(G_OBJECT(source->linked));
-        type = PyLong_FromLong(source->type);
+        type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
+                                                   "InstructionLinkType", source->type);
 
 #ifndef NDEBUG
         ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
@@ -784,15 +795,25 @@ static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unus
 {
     PyObject *result;                       /* Instance à retourner        */
     GArchInstruction *instr;                /* Version native              */
-    const instr_link_t *dest;               /* Destination des liens       */
     size_t count;                           /* Nombre de liens présents    */
     size_t i;                               /* Boucle de parcours          */
+    const instr_link_t *dest;               /* Destination des liens       */
     PyObject *linked;                       /* Destination de lien Python  */
     PyObject *type;                         /* Nature du lien en Python    */
 #ifndef NDEBUG
     int ret;                                /* Bilan d'une écriture d'arg. */
 #endif
 
+#define ARCH_INSTRUCTION_DESTINATIONS_ATTRIB PYTHON_GET_DEF_FULL            \
+(                                                                           \
+    destinations, py_arch_instruction,                                      \
+    "Provide the instructions list following the current instruction.\n"    \
+    "\n"                                                                    \
+    "Each item of the resulting tuple is a pair of"                         \
+    " pychrysalide.arch.ArchInstruction instance and"                       \
+    " pychrysalide.arch.ArchInstruction.InstructionLinkType value."         \
+)
+
     instr = G_ARCH_INSTRUCTION(pygobject_get(self));
 
     g_arch_instruction_lock_dest(instr);
@@ -806,7 +827,8 @@ static PyObject *py_arch_instruction_get_destinations(PyObject *self, void *unus
         dest = g_arch_instruction_get_destination(instr, i);
 
         linked = pygobject_new(G_OBJECT(dest->linked));
-        type = PyLong_FromLong(dest->type);
+        type = cast_with_constants_group_from_type(get_python_arch_instruction_type(),
+                                                   "InstructionLinkType", dest->type);
 
 #ifndef NDEBUG
         ret = PyTuple_SetItem(result, i, Py_BuildValue("(OO)", linked, type));
@@ -1005,14 +1027,8 @@ PyTypeObject *get_python_arch_instruction_type(void)
             "operands", (getter)py_arch_instruction_get_operands, (setter)NULL,
             "Provide the list of instruction attached operands.", NULL
         },
-        {
-            "sources", (getter)py_arch_instruction_get_sources, (setter)NULL,
-            "Provide the instructions list driving to the current instruction."
-        },
-        {
-            "destinations", (getter)py_arch_instruction_get_destinations, (setter)NULL,
-            "Provide the instructions list following the current instruction."
-        },
+        ARCH_INSTRUCTION_SOURCES_ATTRIB,
+        ARCH_INSTRUCTION_DESTINATIONS_ATTRIB,
         { NULL }
     };
 
-- 
cgit v0.11.2-87-g4458