summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/analysis/scan/item.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/analysis/scan/item.c')
-rw-r--r--plugins/pychrysalide/analysis/scan/item.c413
1 files changed, 406 insertions, 7 deletions
diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c
index 959694e..3f46067 100644
--- a/plugins/pychrysalide/analysis/scan/item.c
+++ b/plugins/pychrysalide/analysis/scan/item.c
@@ -38,14 +38,68 @@
-CREATE_DYN_CONSTRUCTOR(registered_item, G_TYPE_REGISTERED_ITEM);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Initialise la classe des éléments appelables enregistrés. */
+static void py_registered_item_init_gclass(GRegisteredItemClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(registered_item, G_TYPE_REGISTERED_ITEM, py_registered_item_init_gclass);
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_registered_item_init(PyObject *, PyObject *, PyObject *);
+/* Indique le nom associé à une expression d'évaluation. */
+static char *py_registered_item_get_name_wrapper(const GRegisteredItem *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool py_registered_item_resolve_wrapper(GRegisteredItem *, const char *, GScanContext *, GScanScope *, GRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool py_registered_item_reduce_wrapper(GRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue un appel à une fonction enregistrée. */
+static bool py_registered_item_run_call_wrapper(GRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
/* Lance une résolution d'élément à appeler. */
static PyObject *py_registered_item_resolve(PyObject *, PyObject *);
+/* Fournit le désignation associée à un composant nommé. */
+static PyObject *py_registered_item_get_name(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe des éléments appelables enregistrés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_registered_item_init_gclass(GRegisteredItemClass *class, gpointer unused)
+{
+ class->get_name = py_registered_item_get_name_wrapper;
+ class->resolve = py_registered_item_resolve_wrapper;
+ class->reduce = py_registered_item_reduce_wrapper;
+ class->run_call = py_registered_item_run_call_wrapper;
+
+}
/******************************************************************************
@@ -66,13 +120,22 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd
{
int ret; /* Bilan de lecture des args. */
-#define REGISTERED_ITEM_DOC \
- "The *RegisteredItem* class defines the basics for evaluation" \
- " items involved into content scanning.\n" \
+#define REGISTERED_ITEM_DOC \
+ "The *RegisteredItem* class is an abstract definition which is" \
+ " the base for all keywords involved in a match condition" \
+ " expression.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object" \
+ " expect no particular argument.\n" \
"\n" \
- "Instances can be created using the following constructor:\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._resolve();\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._reduce();\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._call().\n" \
"\n" \
- " RegisteredItem()"
+ "One item has to be defined as class attributes in the final" \
+ " class:\n" \
+ "* pychrysalide.analysis.scan.RegisteredItem._name.\n"
/* Initialisation d'un objet GLib */
@@ -86,6 +149,338 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd
/******************************************************************************
* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_registered_item_get_name_wrapper(const GRegisteredItem *item)
+{
+ char *result; /* Désignation à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyname; /* Nom en objet Python */
+ int ret; /* Bilan d'une conversion */
+
+#define REGISTERED_ITEM_NAME_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF \
+( \
+ _name, \
+ "Provide the keyword of the expression item to be evaluated.\n" \
+ "\n" \
+ "The result has to be a string." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (PyObject_HasAttrString(pyobj, "_name"))
+ {
+ pyname = PyObject_GetAttrString(pyobj, "_name");
+
+ if (pyname != NULL)
+ {
+ ret = PyUnicode_Check(pyname);
+
+ if (ret)
+ result = strdup(PyUnicode_AsUTF8(pyname));
+
+ Py_DECREF(pyname);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_registered_item_resolve_wrapper(GRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define REGISTERED_ITEM_RESOLVE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, target, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to resolve an item by name.\n" \
+ "\n" \
+ "The *target* argument provide the name of the searched item;" \
+ " *ctx* is a pychrysalide.analysis.scan.ScanContext instance" \
+ " providing information about the current state; *scope* is a" \
+ " pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.RegisteredItem" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_resolve"))
+ {
+ args = PyTuple_New(3);
+ PyTuple_SetItem(args, 0, PyUnicode_FromString(target));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_resolve", args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_REGISTERED_ITEM(gobj_ret))
+ {
+ *out = G_REGISTERED_ITEM(gobj_ret);
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_registered_item_reduce_wrapper(GRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define REGISTERED_ITEM_REDUCE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to replace the item by an equivalent reduced" \
+ " value.\n" \
+ "\n" \
+ "The *ctx* argument is a pychrysalide.analysis.scan.ScanContext" \
+ " instance providing information about the current state; *scope*" \
+ " is a pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.ScanExpression" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_reduce"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_reduce", args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_SCAN_EXPRESSION(gobj_ret))
+ {
+ *out = G_SCAN_EXPRESSION(gobj_ret);
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Effectue un appel à une fonction enregistrée. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_registered_item_run_call_wrapper(GRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *sub_args; /* Sous-arguments pour l'appel */
+ size_t i; /* Boucle de parcours */
+ PyObject *py_args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ GObject *gobj_ret; /* Bilan natif de consultation */
+
+#define REGISTERED_ITEM_CALL_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, args, ctx, scope, /", \
+ METH_VARARGS, \
+ "Abstract method used to replace the item and its arguments by an" \
+ " equivalent reduced value.\n" \
+ "\n" \
+ "The *args* argument is a tuple of already reduced" \
+ " pychrysalide.analysis.scan.ScanExpression objects; ctx* argument" \
+ " is a pychrysalide.analysis.scan.ScanContext instance providing" \
+ " information about the current state; *scope* is a" \
+ " pychrysalide.analysis.scan.ScanScope offering a view on the" \
+ " current namespace for variables.\n" \
+ "\n" \
+ "The result has to be a pychrysalide.analysis.scan.ScanExpression" \
+ " instance on success, or *None* in case of failure." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_call"))
+ {
+ sub_args = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(sub_args, 1, pygobject_new(G_OBJECT(args[i])));
+
+ py_args = PyTuple_New(3);
+ PyTuple_SetItem(py_args, 0, sub_args);
+ PyTuple_SetItem(py_args, 1, pygobject_new(G_OBJECT(ctx)));
+ PyTuple_SetItem(py_args, 2, pygobject_new(G_OBJECT(scope)));
+
+ pyret = run_python_method(pyobj, "_call", py_args);
+
+ if (pyret != NULL)
+ {
+ gobj_ret = pygobject_get(pyret);
+
+ if (G_IS_OBJECT(gobj_ret))
+ {
+ *out = gobj_ret;
+
+ g_object_ref(G_OBJECT(*out));
+ result = true;
+
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(py_args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
* Paramètres : self = élément d'appel à consulter. *
* args = arguments fournis pour l'opération. *
* *
@@ -227,11 +622,15 @@ static PyObject *py_registered_item_get_name(PyObject *self, void *closure)
PyTypeObject *get_python_registered_item_type(void)
{
static PyMethodDef py_registered_item_methods[] = {
+ REGISTERED_ITEM_RESOLVE_WRAPPER,
+ REGISTERED_ITEM_REDUCE_WRAPPER,
+ REGISTERED_ITEM_CALL_WRAPPER,
REGISTERED_ITEM_RESOLVE_METHOD,
{ NULL }
};
static PyGetSetDef py_registered_item_getseters[] = {
+ REGISTERED_ITEM_NAME_ATTRIB_WRAPPER,
REGISTERED_ITEM_NAME_ATTRIB,
{ NULL }
};
@@ -243,7 +642,7 @@ PyTypeObject *get_python_registered_item_type(void)
.tp_name = "pychrysalide.analysis.scan.RegisteredItem",
.tp_basicsize = sizeof(PyGObject),
- .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
.tp_doc = REGISTERED_ITEM_DOC,