summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/arch
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-08-22 17:57:19 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-08-22 17:59:06 (GMT)
commitf94210f2617968774277078a8db9097c56029039 (patch)
treeb65eb802595a4496e931fe124010ad6f7b995272 /plugins/pychrysalide/arch
parent1e4bc888ff02d21b8fe4a45c70298624f35e758a (diff)
Defined paths to access to the instruction operands.
Diffstat (limited to 'plugins/pychrysalide/arch')
-rw-r--r--plugins/pychrysalide/arch/instruction.c126
-rw-r--r--plugins/pychrysalide/arch/operand.c298
2 files changed, 415 insertions, 9 deletions
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 058106d..fcd0c83 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -26,6 +26,7 @@
#include <assert.h>
+#include <malloc.h>
#include <string.h>
#include <pygobject.h>
@@ -122,6 +123,12 @@ static PyObject *py_arch_instruction_replace_operand(PyObject *, PyObject *);
/* Détache un opérande liée d'une instruction. */
static PyObject *py_arch_instruction_detach_operand(PyObject *, PyObject *);
+/* Détermine le chemin conduisant à un opérande. */
+static PyObject *py_arch_instruction_find_operand_path(PyObject *, PyObject *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static PyObject *py_arch_instruction_get_operand_from_path(PyObject *, PyObject *);
+
/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
@@ -578,6 +585,123 @@ static PyObject *py_arch_instruction_detach_operand(PyObject *self, PyObject *ar
}
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Détermine le chemin conduisant à un opérande. *
+* *
+* Retour : Chemin d'accès à l'opérande ou None en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_find_operand_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Chemin à retourner */
+ GArchOperand *target; /* Opérande ciblé par l'action */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ char *path; /* Chemin déterminé */
+
+#define ARCH_INSTRUCTION_FIND_OPERAND_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ find_operand_path, "$self, target, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Compute the path leading to an instruction operand.\n" \
+ "\n" \
+ "The *target* has to be an instance of pychrysalide.arch.ArchOperand" \
+ " included in the instruction.\n" \
+ "\n" \
+ "The result is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index, or None if the *target* is not found. This kind of" \
+ " path is aimed to be built for the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target);
+ if (!ret) return NULL;
+
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+ path = g_arch_instruction_find_operand_path(instr, target);
+
+ if (path != NULL)
+ {
+ result = PyUnicode_FromString(path);
+ free(path);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_get_operand_from_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ const char *path; /* Chemin à parcourir */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ GArchOperand *op; /* Opérande retrouvé */
+
+#define ARCH_INSTRUCTION_GET_OPERAND_FROM_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ get_operand_from_path, "$self, path, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Retrieve an operand from an instruction by its path.\n" \
+ "\n" \
+ "This *path* is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index. Such a path is usually built by the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function.\n" \
+ "\n" \
+ "The result is an pychrysalide.arch.ArchOperand instance, or" \
+ " None if no operand was found." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &path);
+ if (!ret) return NULL;
+
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+ op = g_arch_instruction_get_operand_from_path(instr, path);
+
+ if (op != NULL)
+ {
+ result = pygobject_new(G_OBJECT(op));
+ g_object_unref(G_OBJECT(op));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
@@ -859,6 +983,8 @@ PyTypeObject *get_python_arch_instruction_type(void)
METH_VARARGS,
"detach_operand($self, target, /)\n--\n\nRemove an operand from the instruction."
},
+ ARCH_INSTRUCTION_FIND_OPERAND_PATH_METHOD,
+ ARCH_INSTRUCTION_GET_OPERAND_FROM_PATH_METHOD,
{ NULL }
};
diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c
index 019e4a2..7fa5118 100644
--- a/plugins/pychrysalide/arch/operand.c
+++ b/plugins/pychrysalide/arch/operand.c
@@ -50,6 +50,12 @@ static void py_arch_operand_init_gclass(GArchOperandClass *, gpointer);
/* Compare un opérande avec un autre. */
static int py_arch_operand___cmp___wrapper(const GArchOperand *, const GArchOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const GArchOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void py_arch_operand_print_wrapper(const GArchOperand *, GBufferLine *);
@@ -64,6 +70,12 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const G
/* Effectue une comparaison avec un objet Python 'ArchOperand'. */
static PyObject *py_arch_operand_richcompare(PyObject *, PyObject *, int);
+/* Détermine le chemin conduisant à un opérande interne. */
+static PyObject *py_arch_operand_find_inner_operand_path(PyObject *, PyObject *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *, PyObject *);
+
/* ---------------------------------------------------------------------------------- */
@@ -105,6 +117,10 @@ static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObjec
"* pychrysalide.arch.ArchRegister._print();\n" \
"* pychrysalide.arch.ArchRegister._build_tooltip().\n" \
"\n" \
+ "Some extra method definitions are optional for new classes:\n" \
+ "* pychrysalide.arch.ArchRegister._find_inner_operand_path();\n" \
+ "* pychrysalide.arch.ArchRegister._get_inner_operand_from_path().\n"\
+ "\n" \
"Chrysalide creates an internal glue to provide rich comparisons" \
" for operands based on the old-style *__cmp__* function."
@@ -165,6 +181,9 @@ static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObjec
static void py_arch_operand_init_gclass(GArchOperandClass *class, gpointer unused)
{
class->compare = py_arch_operand___cmp___wrapper;
+ class->find_inner = py_arch_operand_find_inner_operand_path_wrapper;
+ class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper;
+
class->print = py_arch_operand_print_wrapper;
class->build_tooltip = py_arch_operand_build_tooltip_wrapper;
@@ -224,10 +243,154 @@ static int py_arch_operand___cmp___wrapper(const GArchOperand *a, const GArchOpe
result = PyLong_AsLong(pyret);
}
+ Py_XDECREF(pyret);
+
Py_DECREF(args);
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _find_inner_operand_path, "$self, target, /", \
+ METH_VARARGS, \
+ "Abstract method used to compute the path leading to an inner" \
+ " operand.\n" \
+ "\n" \
+ "The *target* has to be an instance of pychrysalide.arch.ArchOperand" \
+ " included in the operand.\n" \
+ "\n" \
+ "The result is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index, or None if the *target* is not found. This kind of" \
+ " path is aimed to be built for the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(operand));
+
+ if (has_python_method(pyobj, "_find_inner_operand_path"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(target)));
+
+ pyret = run_python_method(pyobj, "_find_inner_operand_path", args);
+
+ if (pyret != NULL)
+ {
+ if (PyUnicode_Check(pyret))
+ result = strdup(PyUnicode_AsUTF8(pyret));
+ }
+
Py_XDECREF(pyret);
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const GArchOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_inner_operand_from_path, "$self, path, /", \
+ METH_VARARGS, \
+ "Abstract method used to retrieve an inner operand by its path.\n" \
+ "\n" \
+ "This *path* is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index. Such a path is usually built by the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function.\n" \
+ "\n" \
+ "The result is an pychrysalide.arch.ArchOperand instance, or" \
+ " None if no operand was found." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(operand));
+
+ if (has_python_method(pyobj, "_get_inner_operand_from_path"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, PyUnicode_FromString(path));
+
+ pyret = run_python_method(pyobj, "_get_inner_operand_from_path", args);
+
+ if (pyret != NULL)
+ {
+ if (PyObject_TypeCheck(pyret, get_python_arch_operand_type()))
+ {
+ result = G_ARCH_OPERAND(pygobject_get(pyret));
+ g_object_ref(G_OBJECT(result));
+ }
+
+ }
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
}
Py_DECREF(pyobj);
@@ -278,10 +441,10 @@ static void py_arch_operand_print_wrapper(const GArchOperand *operand, GBufferLi
pyret = run_python_method(pyobj, "_print", args);
- Py_DECREF(args);
-
Py_XDECREF(pyret);
+ Py_DECREF(args);
+
}
Py_DECREF(pyobj);
@@ -311,7 +474,6 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand,
PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Bilan de consultation */
- int ret; /* Bilan d'une conversion */
#define ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER PYTHON_WRAPPER_DEF \
( \
@@ -339,15 +501,12 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand,
if (pyret != NULL)
{
- ret = PyUnicode_Check(pyret);
-
- if (ret)
+ if (PyUnicode_Check(pyret))
result = strdup(PyUnicode_AsUTF8(pyret));
-
- Py_DECREF(pyret);
-
}
+ Py_XDECREF(pyret);
+
Py_DECREF(args);
}
@@ -414,6 +573,123 @@ static PyObject *py_arch_operand_richcompare(PyObject *a, PyObject *b, int op)
/******************************************************************************
* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou None en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_operand_find_inner_operand_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Chemin à retourner */
+ GArchOperand *target; /* Opérande ciblé par l'action */
+ int ret; /* Bilan de lecture des args. */
+ GArchOperand *operand; /* Opérande manipulé */
+ char *path; /* Chemin déterminé */
+
+#define ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ find_inner_operand_path, "$self, target, /", \
+ METH_VARARGS, py_arch_operand, \
+ "Compute the path leading to an inner operand.\n" \
+ "\n" \
+ "The *target* has to be an instance of pychrysalide.arch.ArchOperand" \
+ " included in the operand.\n" \
+ "\n" \
+ "The result is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index, or None if the *target* is not found. This kind of" \
+ " path is aimed to be built for the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target);
+ if (!ret) return NULL;
+
+ operand = G_ARCH_OPERAND(pygobject_get(self));
+
+ path = g_arch_operand_find_inner_operand_path(operand, target);
+
+ if (path != NULL)
+ {
+ result = PyUnicode_FromString(path);
+ free(path);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ const char *path; /* Chemin à parcourir */
+ int ret; /* Bilan de lecture des args. */
+ GArchOperand *operand; /* Opérande manipulé */
+ GArchOperand *op; /* Opérande retrouvé */
+
+#define ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ get_inner_operand_from_path, "$self, path, /", \
+ METH_VARARGS, py_arch_operand, \
+ "Retrieve an inner operand by its path.\n" \
+ "\n" \
+ "This *path* is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index. Such a path is usually built by the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function.\n" \
+ "\n" \
+ "The result is an pychrysalide.arch.ArchOperand instance, or" \
+ " None if no operand was found." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &path);
+ if (!ret) return NULL;
+
+ operand = G_ARCH_OPERAND(pygobject_get(self));
+
+ op = g_arch_operand_get_inner_operand_from_path(operand, path);
+
+ if (op != NULL)
+ {
+ result = pygobject_new(G_OBJECT(op));
+ g_object_unref(G_OBJECT(op));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -428,8 +704,12 @@ PyTypeObject *get_python_arch_operand_type(void)
{
static PyMethodDef py_arch_operand_methods[] = {
ARCH_OPERAND_CMP_WRAPPER,
+ ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER,
+ ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER,
ARCH_OPERAND_PRINT_WRAPPER,
ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER,
+ ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD,
+ ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD,
{ NULL }
};