From c87020ce7d1cd0a46f8122839c53ffa3e49fd172 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 2 Jun 2020 22:50:17 +0200
Subject: Defined Python extra flags for disassembling errors.

---
 plugins/pychrysalide/arch/constants.c | 95 +++++++++++++++++++++++++++++++++++
 plugins/pychrysalide/arch/constants.h |  6 +++
 plugins/pychrysalide/arch/processor.c | 80 +++++++++++++----------------
 3 files changed, 135 insertions(+), 46 deletions(-)

diff --git a/plugins/pychrysalide/arch/constants.c b/plugins/pychrysalide/arch/constants.c
index 04d0917..0402b03 100644
--- a/plugins/pychrysalide/arch/constants.c
+++ b/plugins/pychrysalide/arch/constants.c
@@ -26,6 +26,7 @@
 
 
 #include <arch/instruction.h>
+#include <arch/processor.h>
 #include <arch/vmpa.h>
 
 
@@ -118,6 +119,100 @@ bool define_arch_instruction_constants(PyTypeObject *type)
 *                                                                             *
 *  Paramètres  : type = type dont le dictionnaire est à compléter.            *
 *                                                                             *
+*  Description : Définit les constantes relatives aux processeurs.            *
+*                                                                             *
+*  Retour      : true en cas de succès de l'opération, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_arch_processor_constants(PyTypeObject *type)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *values;                       /* Groupe de valeurs à établir */
+
+    values = PyDict_New();
+
+    result = add_const_to_group(values, "DISASSEMBLY", APE_DISASSEMBLY);
+    if (result) result = add_const_to_group(values, "LABEL", APE_LABEL);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, true, "ArchProcessingError", values,
+                                            "Flags for error occurring while disassembling instructions.");
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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 constante ArchProcessingError.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_arch_processing_error(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long value;                    /* Valeur transcrite           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 ArchProcessingError");
+            break;
+
+        case 1:
+            value = PyLong_AsUnsignedLong(arg);
+
+            if ((value & (APE_DISASSEMBLY | APE_LABEL)) != 0)
+            {
+                PyErr_SetString(PyExc_TypeError, "invalid value for ArchProcessingError");
+                result = 0;
+            }
+
+            else
+                *((ArchProcessingError *)dst) = value;
+
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type dont le dictionnaire est à compléter.            *
+*                                                                             *
 *  Description : Définit les constantes relatives aux emplacements.           *
 *                                                                             *
 *  Retour      : true en cas de succès de l'opération, false sinon.           *
diff --git a/plugins/pychrysalide/arch/constants.h b/plugins/pychrysalide/arch/constants.h
index 24b3908..03efc82 100644
--- a/plugins/pychrysalide/arch/constants.h
+++ b/plugins/pychrysalide/arch/constants.h
@@ -34,6 +34,12 @@
 /* Définit les constantes relatives aux instructions. */
 bool define_arch_instruction_constants(PyTypeObject *);
 
+/* Définit les constantes relatives aux processeurs. */
+bool define_arch_processor_constants(PyTypeObject *);
+
+/* Tente de convertir en constante ArchProcessingError. */
+int convert_to_arch_processing_error(PyObject *, void *);
+
 /* Définit les constantes relatives aux emplacements. */
 bool define_arch_vmpa_constants(PyTypeObject *);
 
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 43e42ce..80b55d3 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -34,6 +34,7 @@
 #include <plugins/dt.h>
 
 
+#include "constants.h"
 #include "context.h"
 #include "instriter.h"
 #include "instruction.h"
@@ -137,14 +138,6 @@ static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *);
 
 
 
-/* ---------------------------- DEFINITION DE PROCESSEUR ---------------------------- */
-
-
-/* Définit les constantes pour les types d'erreurs. */
-static bool define_python_arch_processor_constants(PyTypeObject *);
-
-
-
 /* ---------------------------------------------------------------------------------- */
 /*                          GLUE POUR CREATION DEPUIS PYTHON                          */
 /* ---------------------------------------------------------------------------------- */
@@ -1104,7 +1097,21 @@ static PyObject *py_arch_processor_add_error(PyObject *self, PyObject *args)
     int ret;                                /* Bilan de lecture des args.  */
     GArchProcessor *proc;                   /* Processeur manipulé         */
 
-    ret = PyArg_ParseTuple(args, "IO&s", &type, convert_any_to_vmpa, &addr, &desc);
+#define ARCH_PROCESSOR_ADD_ERROR_METHOD PYTHON_METHOD_DEF           \
+(                                                                   \
+    add_error, "$self, type, addr, desc, /",                        \
+    METH_VARARGS, py_arch_processor,                                \
+    "Extend the list of detected disassembling errors.\n"           \
+    "\n"                                                            \
+    "The type of error has to be one of the"                        \
+    " pychrysalide.arch.ArchProcessor.ArchProcessingError flags."   \
+    " The location of the error is a pychrysalide.arch.vmpa"        \
+    " instance and a one-line description should give some details" \
+    " about what has failed."                                       \
+)
+
+    ret = PyArg_ParseTuple(args, "O&O&s", convert_to_arch_processing_error, &type,
+                           convert_any_to_vmpa, &addr, &desc);
     if (!ret) return NULL;
 
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
@@ -1143,8 +1150,19 @@ static PyObject *py_arch_processor_get_errors(PyObject *self, void *closure)
     ArchProcessingError type;               /* Type d'erreur détectée      */
     vmpa2t addr;                            /* Position d'une erreur       */
     char *desc;                             /* Description d'une erreur    */
+    PyObject *py_type;                      /* Version Python du type      */
     PyObject *error;                        /* Nouvelle erreur à rajouter  */
 
+#define ARCH_PROCESSOR_ERRORS_ATTRIB PYTHON_GET_DEF_FULL                                \
+(                                                                                       \
+    errors, py_arch_processor,                                                          \
+    "List of all detected errors which occurred during the disassembling process.\n"    \
+    "\n"                                                                                \
+    "The result is a tuple of (pychrysalide.arch.ArchProcessor.ArchProcessingError,"    \
+    " pychrysalide.arch.vmpa, string) values, providing a location and a description"   \
+    " for each error."                                                                  \
+)
+
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
 
     g_arch_processor_lock_errors(proc);
@@ -1162,7 +1180,10 @@ static PyObject *py_arch_processor_get_errors(PyObject *self, void *closure)
         g_arch_processor_get_error(proc, i, &type, &addr, &desc);
 #endif
 
-        error = Py_BuildValue("IO&s", type, build_from_internal_vmpa, &addr, desc);
+        py_type = cast_with_constants_group_from_type(get_python_arch_processor_type(),
+                                                      "ArchProcessingError", type);
+        error = Py_BuildValue("OO&s", py_type, build_from_internal_vmpa, &addr, desc);
+        Py_DECREF(py_type);
 
         PyTuple_SetItem(result, i, error);
 
@@ -1334,32 +1355,6 @@ static PyObject *py_arch_processor_find_instr_by_addr(PyObject *self, PyObject *
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
-*                                                                             *
-*  Description : Définit les constantes pour les types d'erreurs.             *
-*                                                                             *
-*  Retour      : true en cas de succès de l'opération, false sinon.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool define_python_arch_processor_constants(PyTypeObject *obj_type)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = true;
-
-    result &= PyDict_AddULongMacro(obj_type, APE_DISASSEMBLY);
-    result &= PyDict_AddULongMacro(obj_type, APE_LABEL);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -1383,11 +1378,7 @@ PyTypeObject *get_python_arch_processor_type(void)
             METH_VARARGS,
             "disassemble($self, context, content, pos, format, /)\n--\n\nDisassemble a portion of binary content into one instruction."
         },
-        {
-            "add_error", py_arch_processor_add_error,
-            METH_VARARGS,
-            "add_error($self, type, addr, desc, /)\n--\n\nExtend the list of detected disassembling errors."
-        },
+        ARCH_PROCESSOR_ADD_ERROR_METHOD,
         {
             "find_instr_by_addr", py_arch_processor_find_instr_by_addr,
             METH_VARARGS,
@@ -1403,10 +1394,7 @@ PyTypeObject *get_python_arch_processor_type(void)
         ARCH_PROCESSOR_MEMORY_SIZE_ATTRIB,
         ARCH_PROCESSOR_INS_MIN_SIZE_ATTRIB,
         ARCH_PROCESSOR_VIRTUAL_SPACE_ATTRIB,
-        {
-            "errors", py_arch_processor_get_errors, NULL,
-            "List of all detected errors which occurred during the disassembling process.", NULL
-        },
+        ARCH_PROCESSOR_ERRORS_ATTRIB,
         {
             "instrs", py_arch_processor_get_instrs, py_arch_processor_set_instrs,
             "Give access to the disassembled instructions run by the current processor.", NULL
@@ -1467,7 +1455,7 @@ bool ensure_python_arch_processor_is_registered(void)
         if (!register_class_for_pygobject(dict, G_TYPE_ARCH_PROCESSOR, type, &PyGObject_Type))
             return false;
 
-        if (!define_python_arch_processor_constants(type))
+        if (!define_arch_processor_constants(type))
             return false;
 
     }
-- 
cgit v0.11.2-87-g4458