diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2020-10-10 12:01:40 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2020-10-10 12:01:40 (GMT) |
commit | 0b0f69bd1278b8f5d95c6ea8fb56915148992a77 (patch) | |
tree | 0d9ab819a636c6d7bf61e09856283efd1562353a /plugins/pychrysalide/analysis | |
parent | 1af362266f616aed07e2661c9676c67dc3365740 (diff) |
Updated the basic types definition and its Python bindings.
Diffstat (limited to 'plugins/pychrysalide/analysis')
-rw-r--r-- | plugins/pychrysalide/analysis/constants.c | 98 | ||||
-rw-r--r-- | plugins/pychrysalide/analysis/constants.h | 6 | ||||
-rw-r--r-- | plugins/pychrysalide/analysis/type.c | 707 | ||||
-rw-r--r-- | plugins/pychrysalide/analysis/type.h | 3 |
4 files changed, 744 insertions, 70 deletions
diff --git a/plugins/pychrysalide/analysis/constants.c b/plugins/pychrysalide/analysis/constants.c index dc507dc..8d68edc 100644 --- a/plugins/pychrysalide/analysis/constants.c +++ b/plugins/pychrysalide/analysis/constants.c @@ -25,6 +25,7 @@ #include "constants.h" +#include <analysis/type.h> #include <common/endianness.h> @@ -212,3 +213,100 @@ int convert_to_memory_data_size(PyObject *arg, void *dst) return result; } + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les types de données. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_analysis_data_type_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + values = PyDict_New(); + + result = add_const_to_group(values, "NONE", TQF_NONE); + if (result) result = add_const_to_group(values, "RESTRICT", TQF_RESTRICT); + if (result) result = add_const_to_group(values, "VOLATILE", TQF_VOLATILE); + if (result) result = add_const_to_group(values, "CONST", TQF_CONST); + if (result) result = add_const_to_group(values, "ALL", TQF_ALL); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, false, "TypeQualifier", values, + "Qualifier for a data type."); + + 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 TypeQualifier. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_data_type_qualifier(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 TypeQualifier"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if ((value & ~TQF_ALL) != 0) + { + PyErr_SetString(PyExc_TypeError, "invalid value for TypeQualifier"); + result = 0; + } + + else + *((TypeQualifier *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/constants.h b/plugins/pychrysalide/analysis/constants.h index 45982bb..fb96e99 100644 --- a/plugins/pychrysalide/analysis/constants.h +++ b/plugins/pychrysalide/analysis/constants.h @@ -39,6 +39,12 @@ int convert_to_source_endian(PyObject *, void *); /* Tente de convertir en constante MemoryDataSize. */ int convert_to_memory_data_size(PyObject *, void *); +/* Définit les constantes pour les types de données. */ +bool define_analysis_data_type_constants(PyTypeObject *); + +/* Tente de convertir en constante TypeQualifier. */ +int convert_to_data_type_qualifier(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_CONSTANTS_H */ diff --git a/plugins/pychrysalide/analysis/type.c b/plugins/pychrysalide/analysis/type.c index 6043042..cd849e4 100644 --- a/plugins/pychrysalide/analysis/type.c +++ b/plugins/pychrysalide/analysis/type.c @@ -33,17 +33,54 @@ #include <i18n.h> -#include <analysis/type.h> +#include <analysis/type-int.h> +#include <plugins/dt.h> +#include "constants.h" #include "../access.h" #include "../helpers.h" +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_data_type_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise la classe des types quelconques. */ +static void py_data_type_init_gclass(GDataTypeClass *, gpointer); + +/* Crée un copie d'un type existant. */ +static GDataType *py_data_type_dup_wrapper(const GDataType *); + +/* Décrit le type fourni sous forme de caractères. */ +static char *py_data_type_to_string_wrapper(const GDataType *, bool); + +/* Indique si le type assure une gestion des espaces de noms. */ +static bool py_data_type_handle_namespaces_wrapper(const GDataType *); + +/* Indique si le type est un pointeur. */ +static bool py_data_type_is_pointer_wrapper(const GDataType *); + +/* Indique si le type est une référence. */ +static bool py_data_type_is_reference_wrapper(const GDataType *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_data_type_init(PyObject *, PyObject *, PyObject *); + + + +/* ----------------- FONCTIONNALITES BASIQUES POUR TYPES DE DONNEES ----------------- */ + + /* Décrit le type fourni sous forme de caractères. */ static PyObject *py_data_type_to_str(PyObject *); +/* Crée un copie d'un type existant. */ +static PyObject *py_data_type_dup(PyObject *, PyObject *); + /* Fournit le groupe d'appartenance d'un type donné. */ static PyObject *py_data_type_get_namespace(PyObject *, void *); @@ -56,16 +93,432 @@ static PyObject *py_data_type_get_qualifiers(PyObject *, void *); /* Définit l'ensemble des qualificatifs d'une instance de type. */ static int py_data_type_set_qualifiers(PyObject *, PyObject *, void *); +/* Indique si le type assure une gestion des espaces de noms. */ +static PyObject *py_data_type_handle_namespaces(PyObject *, void *); + /* Indique si le type est un pointeur. */ static PyObject *py_data_type_is_pointer(PyObject *, void *); /* Indique si le type est une référence. */ static PyObject *py_data_type_is_reference(PyObject *, void *); -/* Définit les constantes pour les types de données. */ -static bool py_data_type_define_constants(PyTypeObject *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_data_type_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_data_type_type(); + + if (type == base) + { + result = NULL; + PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); + goto exit; + } + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_DATA_TYPE, type->tp_name, + (GClassInitFunc)py_data_type_init_gclass, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type, base); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * +* * +* Description : Initialise la classe des types quelconques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_data_type_init_gclass(GDataTypeClass *class, gpointer unused) +{ + class->dup = py_data_type_dup_wrapper; + class->to_string = py_data_type_to_string_wrapper; + + class->handle_ns = py_data_type_handle_namespaces_wrapper; + class->is_pointer = py_data_type_is_pointer_wrapper; + class->is_reference = py_data_type_is_reference_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à dupliquer. * +* * +* Description : Crée un copie d'un type existant. * +* * +* Retour : Nouvelle instance de type identique à celle fournie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDataType *py_data_type_dup_wrapper(const GDataType *type) +{ + GDataType *result; /* Copie à retourner */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define DATA_TYPE_DUP_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _dup, "$self, /", \ + METH_NOARGS, \ + "Abstract method used to create a copy of a data type.\n" \ + "\n" \ + "The returned value has to be a new instance of the" \ + " pychrysalide.analysis.DataType class." \ +) + + result = NULL; + + pyobj = pygobject_new(G_OBJECT(type)); + + if (has_python_method(pyobj, "_dup")) + { + pyret = run_python_method(pyobj, "_dup", NULL); + + if (pyret != NULL) + { + if (PyObject_TypeCheck(pyret, get_python_data_type_type())) + { + result = G_DATA_TYPE(pygobject_get(pyret)); + g_object_ref(G_OBJECT(result)); + } + } + + Py_XDECREF(pyret); + + } + + Py_DECREF(pyobj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à convertir. * +* include = doit-on inclure les espaces de noms ? * +* * +* Description : Décrit le type fourni sous forme de caractères. * +* * +* Retour : Chaîne à libérer de la mémoire après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_data_type_to_string_wrapper(const GDataType *type, bool include) +{ + char *result; /* Etiquette à retourner */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *arg; /* Version Python de l'argument*/ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + +#define DATA_TYPE_TO_STRING_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _to_string, "$self, include, /", \ + METH_VARARGS, \ + "Abstract method used to provide the string represention of" \ + " a data type.\n" \ + "\n" \ + "The *include* argument defines if the type namespace has to" \ + " get prepended, if it exists.\n" \ + "\n" \ + "The returned value has to be a string." \ +) + + result = NULL; + + pyobj = pygobject_new(G_OBJECT(type)); + + if (has_python_method(pyobj, "_to_string")) + { + arg = include ? Py_True : Py_False; + Py_INCREF(arg); + + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, arg); + + pyret = run_python_method(pyobj, "_to_string", args); + + if (pyret != NULL) + { + if (PyUnicode_Check(pyret)) + result = strdup(PyUnicode_DATA(pyret)); + } + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à consulter. * +* * +* Description : Indique si le type assure une gestion des espaces de noms. * +* * +* Retour : Bilan de la consultation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_data_type_handle_namespaces_wrapper(const GDataType *type) +{ + bool result; /* Bilan à retourner */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define DATA_TYPE_HANDLE_NAMESPACES_WRAPPER PYTHON_TRUE_WRAPPER_DEF \ +( \ + _handle_namespaces, "$self, /", \ + METH_NOARGS, \ + "Abstract method used to state if the type handles namespaces" \ + " or not.\n" \ + "\n" \ + "The return is a boolean value. If this method does not" \ + " exist, the True value is assumed." \ +) + + result = true; + + pyobj = pygobject_new(G_OBJECT(type)); + + if (has_python_method(pyobj, "_handle_namespaces")) + { + pyret = run_python_method(pyobj, "_handle_namespaces", NULL); + + result = (pyret == Py_True); + + Py_XDECREF(pyret); + + } + + Py_DECREF(pyobj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à consulter. * +* * +* Description : Indique si le type est un pointeur. * +* * +* Retour : Bilan de la consultation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_data_type_is_pointer_wrapper(const GDataType *type) +{ + bool result; /* Bilan à retourner */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define DATA_TYPE_IS_POINTER_WRAPPER PYTHON_FALSE_WRAPPER_DEF \ +( \ + _is_pointer, "$self, /", \ + METH_NOARGS, \ + "Abstract method used to state if the type points to" \ + " another type or not.\n" \ + "\n" \ + "The return is a boolean value. If this method does not" \ + " exist, the False value is assumed." \ +) + + result = false; + + pyobj = pygobject_new(G_OBJECT(type)); + + if (has_python_method(pyobj, "_is_pointer")) + { + pyret = run_python_method(pyobj, "_is_pointer", NULL); + + result = (pyret == Py_True); + + Py_XDECREF(pyret); + + } + + Py_DECREF(pyobj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à consulter. * +* * +* Description : Indique si le type est une référence. * +* * +* Retour : Bilan de la consultation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_data_type_is_reference_wrapper(const GDataType *type) +{ + bool result; /* Bilan à retourner */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define DATA_TYPE_IS_REFERENCE_WRAPPER PYTHON_FALSE_WRAPPER_DEF \ +( \ + _is_reference, "$self, /", \ + METH_NOARGS, \ + "Abstract method used to state if the type refers to" \ + " another type or not.\n" \ + "\n" \ + "The return is a boolean value. If this method does not" \ + " exist, the False value is assumed." \ +) + + result = false; + + pyobj = pygobject_new(G_OBJECT(type)); + + if (has_python_method(pyobj, "_is_reference")) + { + pyret = run_python_method(pyobj, "_is_reference", NULL); + + result = (pyret == Py_True); + + Py_XDECREF(pyret); + + } + + Py_DECREF(pyobj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_data_type_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define DATA_TYPE_DOC \ + "The DataType object is the base class for all data types.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " DataType()" \ + "\n" \ + "The following methods have to be defined for new classes:\n" \ + "* pychrysalide.analysis.DataType._dup();\n" \ + "* pychrysalide.analysis.DataType._to_string()." \ + "\n" \ + "Some extra method definitions are optional for new classes:\n" \ + "* pychrysalide.analysis.DataType._handle_namespaces();\n" \ + "* pychrysalide.analysis.DataType._is_pointer();\n" \ + "* pychrysalide.analysis.DataType._is_reference();" \ + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONNALITES BASIQUES POUR TYPES DE DONNEES */ +/* ---------------------------------------------------------------------------------- */ + /****************************************************************************** * * @@ -100,6 +553,56 @@ static PyObject *py_data_type_to_str(PyObject *self) /****************************************************************************** * * +* Paramètres : self = serveur à manipuler. * +* args = arguments d'appel non utilisés ici. * +* * +* Description : Crée un copie d'un type existant. * +* * +* Retour : Nouvelle instance de type identique à celle fournie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_data_type_dup(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GDataType *type; /* Version native de l'objet */ + GDataType *copy; /* Copie du type obtenue */ + +#define DATA_TYPE_DUP_METHOD PYTHON_METHOD_DEF \ +( \ + dup, "$self, /", \ + METH_NOARGS, py_data_type, \ + "Create a copy of a data type.\n" \ + "\n" \ + "The returned value has to be a new instance of the" \ + " pychrysalide.analysis.DataType class." \ +) + + type = G_DATA_TYPE(pygobject_get(self)); + + copy = g_data_type_dup(type); + + if (copy != NULL) + { + result = pygobject_new(G_OBJECT(copy)); + g_object_unref(G_OBJECT(copy)); + } + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * @@ -116,14 +619,33 @@ static PyObject *py_data_type_get_namespace(PyObject *self, void *closure) PyObject *result; /* Valeur à retourner */ GDataType *type; /* Elément à consulter */ GDataType *ns; /* Espace de noms */ + const char *sep; /* Séparateur d'espace */ + +#define DATA_TYPE_NAMESPACE_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + namespace, py_data_type, \ + "Namespace for the type, None if any.\n" \ + "\n" \ + "This property carries a tuple of two values:\n" \ + "* a namespace, as a pychrysalide.analysis.DataType.TypeQualifier" \ + " instance;\n" \ + "* a namespace separator, as a string." \ +) type = G_DATA_TYPE(pygobject_get(self)); + ns = g_data_type_get_namespace(type); + sep = g_data_type_get_namespace_separator(type); - if (ns != NULL) + if (ns != NULL && sep != NULL) { - result = pygobject_new(G_OBJECT(ns)); + result = PyTuple_New(2); + + PyTuple_SetItem(result, 0, pygobject_new(G_OBJECT(ns))); g_object_unref(G_OBJECT(ns)); + + PyTuple_SetItem(result, 1, PyUnicode_FromString(sep)); + } else @@ -184,7 +706,7 @@ static int py_data_type_set_namespace(PyObject *self, PyObject *value, void *clo } ns = G_DATA_TYPE(pygobject_get(PyTuple_GetItem(value, 0))); - sep = strdup(PyUnicode_DATA(pygobject_get(PyTuple_GetItem(value, 1)))); + sep = strdup(PyUnicode_DATA(PyTuple_GetItem(value, 1))); g_object_ref(G_OBJECT(ns)); g_data_type_set_namespace(type, ns, sep); @@ -215,10 +737,18 @@ static PyObject *py_data_type_get_qualifiers(PyObject *self, void *closure) GDataType *type; /* Elément à consulter */ TypeQualifier qualifiers; /* Qualificatifs en place */ +#define DATA_TYPE_QUALIFIERS_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + qualifiers, py_data_type, \ + "Qualifier for the data type, *TypeQualifier.NONE* if any.\n" \ + "\n" \ + "This property carries a pychrysalide.analysis.DataType.TypeQualifier value." \ +) + type = G_DATA_TYPE(pygobject_get(self)); qualifiers = g_data_type_get_qualifiers(type); - result = PyLong_FromUnsignedLong(qualifiers); + result = cast_with_constants_group_from_type(get_python_data_type_type(), "TypeQualifier", qualifiers); return result; @@ -242,21 +772,11 @@ static PyObject *py_data_type_get_qualifiers(PyObject *self, void *closure) static int py_data_type_set_qualifiers(PyObject *self, PyObject *value, void *closure) { GDataType *type; /* Elément à traiter */ - unsigned long qualifiers; /* Qualificatifs à intégrer */ - - if (!PyLong_Check(value)) - { - PyErr_SetString(PyExc_TypeError, _("The attribute value must be a integer mask.")); - return -1; - } - - qualifiers = PyLong_AsUnsignedLong(value); + TypeQualifier qualifiers; /* Qualificatifs à intégrer */ + int ret; /* Bilan d'une conversion */ - if (qualifiers > TQF_ALL) - { - PyErr_SetString(PyExc_TypeError, _("Invalid value for type qualifiers.")); - return -1; - } + ret = convert_to_data_type_qualifier(value, &qualifiers); + if (ret != 1) return -1; type = G_DATA_TYPE(pygobject_get(self)); @@ -272,6 +792,43 @@ static int py_data_type_set_qualifiers(PyObject *self, PyObject *value, void *cl * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * +* Description : Indique si le type assure une gestion des espaces de noms. * +* * +* Retour : Bilan de la consultation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_data_type_handle_namespaces(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDataType *type; /* Elément à consulter */ + bool status; /* Etat à faire suivre */ + +#define DATA_TYPE_NAMESPACES_ATTRIB PYTHON_RAWGET_DEF_FULL \ +( \ + handle_namespaces, py_data_type, \ + "True if the type handles namespaces, False otherwise." \ +) + + type = G_DATA_TYPE(pygobject_get(self)); + + status = g_data_type_handle_namespaces(type); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * * Description : Indique si le type est un pointeur. * * * * Retour : Bilan de la consultation. * @@ -286,6 +843,12 @@ static PyObject *py_data_type_is_pointer(PyObject *self, void *closure) GDataType *type; /* Elément à consulter */ bool status; /* Etat à faire suivre */ +#define DATA_TYPE_POINTER_ATTRIB PYTHON_IS_DEF_FULL \ +( \ + pointer, py_data_type, \ + "True if the type is a pointer, False otherwise." \ +) + type = G_DATA_TYPE(pygobject_get(self)); status = g_data_type_is_pointer(type); @@ -317,6 +880,12 @@ static PyObject *py_data_type_is_reference(PyObject *self, void *closure) GDataType *type; /* Elément à consulter */ bool status; /* Etat à faire suivre */ +#define DATA_TYPE_REFERENCE_ATTRIB PYTHON_IS_DEF_FULL \ +( \ + reference, py_data_type, \ + "True if the type is a reference, False otherwise." \ +) + type = G_DATA_TYPE(pygobject_get(self)); status = g_data_type_is_reference(type); @@ -344,26 +913,20 @@ static PyObject *py_data_type_is_reference(PyObject *self, void *closure) PyTypeObject *get_python_data_type_type(void) { static PyMethodDef py_data_type_methods[] = { + DATA_TYPE_DUP_WRAPPER, + DATA_TYPE_TO_STRING_WRAPPER, + DATA_TYPE_HANDLE_NAMESPACES_WRAPPER, + DATA_TYPE_IS_POINTER_WRAPPER, + DATA_TYPE_DUP_METHOD, { NULL } }; static PyGetSetDef py_data_type_getseters[] = { - { - "namespace", py_data_type_get_namespace, py_data_type_set_namespace, - "Namespace for the type, None if any.", NULL - }, - { - "qualifiers", py_data_type_get_qualifiers, py_data_type_set_qualifiers, - "Qualifiers linked to the type, TQF_NONE if any.", NULL - }, - { - "is_pointer", py_data_type_is_pointer, NULL, - "True if the type is a pointer.", NULL - }, - { - "is_reference", py_data_type_is_reference, NULL, - "True if the type is a reference.", NULL - }, + DATA_TYPE_NAMESPACE_ATTRIB, + DATA_TYPE_QUALIFIERS_ATTRIB, + DATA_TYPE_NAMESPACES_ATTRIB, + DATA_TYPE_POINTER_ATTRIB, + DATA_TYPE_REFERENCE_ATTRIB, { NULL } }; @@ -377,10 +940,13 @@ PyTypeObject *get_python_data_type_type(void) .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide data type", + .tp_doc = DATA_TYPE_DOC, .tp_methods = py_data_type_methods, - .tp_getset = py_data_type_getseters + .tp_getset = py_data_type_getseters, + + .tp_init = py_data_type_init, + .tp_new = py_data_type_new }; @@ -391,36 +957,6 @@ PyTypeObject *get_python_data_type_type(void) /****************************************************************************** * * -* Paramètres : obj_type = type dont le dictionnaire est à compléter. * -* * -* Description : Définit les constantes pour les types de données. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_data_type_define_constants(PyTypeObject *obj_type) -{ - bool result; /* Bilan à retourner */ - - result = true; - - result &= PyDict_AddULongMacro(obj_type, TQF_NONE); - result &= PyDict_AddULongMacro(obj_type, TQF_RESTRICT); - result &= PyDict_AddULongMacro(obj_type, TQF_VOLATILE); - result &= PyDict_AddULongMacro(obj_type, TQF_CONST); - - result &= PyDict_AddULongMacro(obj_type, TQF_ALL); - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : - * * * * Description : Prend en charge l'objet 'pychrysalide.analysis.DataType'. * @@ -448,7 +984,7 @@ bool ensure_python_data_type_is_registered(void) if (!register_class_for_pygobject(dict, G_TYPE_DATA_TYPE, type, &PyGObject_Type)) return false; - if (!py_data_type_define_constants(type)) + if (!define_analysis_data_type_constants(type)) return false; } @@ -501,3 +1037,34 @@ int convert_to_data_type(PyObject *arg, void *dst) 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 type de donnée ou NULL. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_data_type_or_none(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + if (arg == Py_None) + { + *((GDataType **)dst) = NULL; + result = 1; + } + + else + result = convert_to_data_type(arg, dst); + + return result; + +} diff --git a/plugins/pychrysalide/analysis/type.h b/plugins/pychrysalide/analysis/type.h index 8ea1096..9997a83 100644 --- a/plugins/pychrysalide/analysis/type.h +++ b/plugins/pychrysalide/analysis/type.h @@ -40,6 +40,9 @@ bool ensure_python_data_type_is_registered(void); /* Tente de convertir en type de donnée. */ int convert_to_data_type(PyObject *, void *); +/* Tente de convertir en type de donnée ou NULL. */ +int convert_to_data_type_or_none(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPE_H */ |