From f340a5d363c55d77aca047b6dd85dfaaae02bb6d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 18 Oct 2020 22:11:40 +0200
Subject: Updated the code for the prototypes support.

---
 plugins/itanium/component.c                 |  7 +++
 plugins/pychrysalide/analysis/types/proto.c | 77 +++++++++++++++++++++--------
 src/analysis/types/proto.c                  | 15 +++++-
 3 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
index d891c51..3baad57 100644
--- a/plugins/itanium/component.c
+++ b/plugins/itanium/component.c
@@ -1732,10 +1732,17 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
                 else
                 {
                     if (iter == comp->function.args)
+                    {
                         g_proto_type_set_return_type(G_PROTO_TYPE(result), arg);
+                        g_object_unref(G_OBJECT(arg));
+                    }
 
                     else
+                    {
                         g_proto_type_add_arg(G_PROTO_TYPE(result), arg);
+                        g_object_unref(G_OBJECT(arg));
+                    }
+
                 }
 
             }
diff --git a/plugins/pychrysalide/analysis/types/proto.c b/plugins/pychrysalide/analysis/types/proto.c
index 3eac87f..7c3ebed 100644
--- a/plugins/pychrysalide/analysis/types/proto.c
+++ b/plugins/pychrysalide/analysis/types/proto.c
@@ -74,6 +74,16 @@ static PyObject *py_proto_type_new(PyTypeObject *type, PyObject *args, PyObject
     PyObject *result;                       /* Instance à retourner        */
     GDataType *dtype;                       /* Version GLib du type        */
 
+#define PROTO_TYPE_DOC                                                      \
+    "The ProtoType class defines an empty prototype of function.\n"         \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    ProtoType()"                                                       \
+    "\n"                                                                    \
+    "The arguments and return types have then to be filled in the created"  \
+    " prototype with the relevant methods or properties."
+
     dtype = g_proto_type_new();
     result = pygobject_new(G_OBJECT(dtype));
     g_object_unref(dtype);
@@ -98,19 +108,32 @@ static PyObject *py_proto_type_new(PyTypeObject *type, PyObject *args, PyObject
 
 static PyObject *py_proto_type_add_arg(PyObject *self, PyObject *args)
 {
+    PyObject *result;                       /* Absence de retour Python    */
     GDataType *arg;                         /* Version GLib du type        */
     int ret;                                /* Bilan de lecture des args.  */
     GProtoType *type;                       /* Version GLib du type        */
 
+#define PROTO_TYPE_ADD_PARAM_METHOD PYTHON_METHOD_DEF                   \
+(                                                                       \
+    add_arg, "$self, arg, /",                                           \
+    METH_VARARGS, py_proto_type,                                        \
+    "Add an extra argument to the prototype.\n"                         \
+    "\n"                                                                \
+    "This extra argument has to be a pychrysalide.analysis.DataType"    \
+    " instance."                                                        \
+)
+
     ret = PyArg_ParseTuple(args, "O&", convert_to_data_type, &arg);
     if (!ret) return NULL;
 
     type = G_PROTO_TYPE(pygobject_get(self));
 
-    g_object_ref(G_OBJECT(arg));
     g_proto_type_add_arg(type, arg);
 
-    Py_RETURN_NONE;
+    result = Py_None;
+    Py_INCREF(result);
+
+    return result;
 
 }
 
@@ -134,13 +157,29 @@ static PyObject *py_proto_type_get_return_type(PyObject *self, void *closure)
     GProtoType *type;                       /* Version GLib du type        */
     GDataType *ret;                         /* Type de retour du prototype */
 
+#define PROTO_TYPE_RETURN_TYPE_ATTRIB PYTHON_GETSET_DEF_FULL            \
+(                                                                       \
+    return_type, py_proto_type,                                         \
+    "Type of the prototype return value.\n"                             \
+    "\n"                                                                \
+    "This type is a pychrysalide.analysis.DataType instance,"           \
+    " or None if no return type has been defined for the prototype."    \
+)
+
     type = G_PROTO_TYPE(pygobject_get(self));
 
     ret = g_proto_type_get_return_type(type);
 
-    result = pygobject_new(G_OBJECT(ret));
-
-    g_object_unref(ret);
+    if (ret == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+    else
+    {
+        result = pygobject_new(G_OBJECT(ret));
+        g_object_unref(ret);
+    }
 
     return result;
 
@@ -176,7 +215,6 @@ static int py_proto_type_set_return_type(PyObject *self, PyObject *value, void *
 
     ret = G_DATA_TYPE(pygobject_get(value));
 
-    g_object_ref(ret);
     g_proto_type_set_return_type(type, ret);
 
     return 0;
@@ -205,6 +243,15 @@ static PyObject *py_proto_type_get_args(PyObject *self, void *closure)
     size_t i;                               /* Boucle de parcours          */
     GDataType *arg;                         /* Argument du prototype       */
 
+#define PROTO_TYPE_ARGS_ATTRIB PYTHON_GET_DEF_FULL                      \
+(                                                                       \
+    args, py_proto_type,                                                \
+    "List of all arguments for the prototype.\n"                        \
+    "\n"                                                                \
+    "The returned value is a tuple of pychrysalide.analysis.DataType"   \
+    " instances."                                                       \
+)
+
     type = G_PROTO_TYPE(pygobject_get(self));
 
     count = g_proto_type_count_args(type);
@@ -241,23 +288,13 @@ static PyObject *py_proto_type_get_args(PyObject *self, void *closure)
 PyTypeObject *get_python_proto_type_type(void)
 {
     static PyMethodDef py_proto_type_methods[] = {
-        {
-            "add_arg", py_proto_type_add_arg,
-            METH_VARARGS,
-            "add_arg($self, type, /)\n--\n\nAdd an extra argument to the prototype."
-        },
+        PROTO_TYPE_ADD_PARAM_METHOD,
         { NULL }
     };
 
     static PyGetSetDef py_proto_type_getseters[] = {
-        {
-            "return", py_proto_type_get_return_type, py_proto_type_set_return_type,
-            "Provide the return type of the prototype.", NULL
-        },
-        {
-            "args", py_proto_type_get_args, NULL,
-            "Give all arguments of the prototype.", NULL
-        },
+        PROTO_TYPE_RETURN_TYPE_ATTRIB,
+        PROTO_TYPE_ARGS_ATTRIB,
         { NULL }
     };
 
@@ -270,7 +307,7 @@ PyTypeObject *get_python_proto_type_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide proto type",
+        .tp_doc         = PROTO_TYPE_DOC,
 
         .tp_methods     = py_proto_type_methods,
         .tp_getset      = py_proto_type_getseters,
diff --git a/src/analysis/types/proto.c b/src/analysis/types/proto.c
index 17f0262..8d5b897 100644
--- a/src/analysis/types/proto.c
+++ b/src/analysis/types/proto.c
@@ -232,12 +232,14 @@ static GDataType *g_proto_type_dup(const GProtoType *type)
     {
         ret_type = g_data_type_dup(type->ret_type);
         g_proto_type_set_return_type(result, ret_type);
+        g_object_unref(G_OBJECT(ret_type));
     }
 
     for (i = 0; i < type->count; i++)
     {
         arg = g_data_type_dup(type->args[i]);
         g_proto_type_add_arg(result, arg);
+        g_object_unref(G_OBJECT(arg));
     }
 
     return G_DATA_TYPE(result);
@@ -363,7 +365,14 @@ void g_proto_type_set_return_type(GProtoType *type, GDataType *ret)
     if (type->ret_type != NULL)
         g_object_unref(G_OBJECT(type->ret_type));
 
-    type->ret_type = ret;
+    if (ret == NULL)
+        type->ret_type = NULL;
+
+    else
+    {
+        g_object_ref(G_OBJECT(ret));
+        type->ret_type = ret;
+    }
 
 }
 
@@ -409,7 +418,9 @@ GDataType *g_proto_type_get_return_type(const GProtoType *type)
 
 void g_proto_type_add_arg(GProtoType *type, GDataType *arg)
 {
-    type->args = (GDataType **)realloc(type->args, ++type->count * sizeof(GDataType *));
+    g_object_ref(G_OBJECT(arg));
+
+    type->args = realloc(type->args, ++type->count * sizeof(GDataType *));
     type->args[type->count - 1] = arg;
 
 }
-- 
cgit v0.11.2-87-g4458