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.c487
1 files changed, 443 insertions, 44 deletions
diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c
index 959694e..014ae24 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_scan_registered_item_init_gclass(GScanRegisteredItemClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_registered_item, G_TYPE_SCAN_REGISTERED_ITEM, py_scan_registered_item_init_gclass);
/* Initialise une instance sur la base du dérivé de GObject. */
-static int py_registered_item_init(PyObject *, PyObject *, PyObject *);
+static int py_scan_registered_item_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue un appel à une fonction enregistrée. */
+static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *, 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 *);
+static PyObject *py_scan_registered_item_resolve(PyObject *, PyObject *);
+
+/* Fournit le désignation associée à un composant nommé. */
+static PyObject *py_scan_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_scan_registered_item_init_gclass(GScanRegisteredItemClass *class, gpointer unused)
+{
+ class->get_name = py_scan_registered_item_get_name_wrapper;
+ class->resolve = py_scan_registered_item_resolve_wrapper;
+ class->reduce = py_scan_registered_item_reduce_wrapper;
+ class->run_call = py_scan_registered_item_run_call_wrapper;
+
+}
/******************************************************************************
@@ -62,17 +116,26 @@ static PyObject *py_registered_item_resolve(PyObject *, PyObject *);
* *
******************************************************************************/
-static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds)
+static int py_scan_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds)
{
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 SCAN_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" \
- "Instances can be created using the following constructor:\n" \
+ "Calls to the *__init__* constructor of this abstract object" \
+ " expect no particular argument.\n" \
"\n" \
- " RegisteredItem()"
+ "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" \
+ "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_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *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 SCAN_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_scan_registered_item_resolve_wrapper(GScanRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **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 SCAN_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_SCAN_REGISTERED_ITEM(gobj_ret))
+ {
+ *out = G_SCAN_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_scan_registered_item_reduce_wrapper(GScanRegisteredItem *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 SCAN_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_scan_registered_item_run_call_wrapper(GScanRegisteredItem *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 SCAN_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. *
* *
@@ -99,21 +494,21 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd
* *
******************************************************************************/
-static PyObject *py_registered_item_resolve(PyObject *self, PyObject *args)
+static PyObject *py_scan_registered_item_resolve(PyObject *self, PyObject *args)
{
PyObject *result; /* Bilan à retourner */
const char *target; /* Désignation de la cible */
GScanContext *ctx; /* Contexte d'analyse */
GScanScope *scope; /* Portée de variables locales */
int ret; /* Bilan de lecture des args. */
- GRegisteredItem *item; /* Version native */
+ GScanRegisteredItem *item; /* Version native */
bool status; /* Bilan d'exécution */
- GRegisteredItem *resolved; /* Elément trouvé */
+ GScanRegisteredItem *resolved; /* Elément trouvé */
-#define REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF \
+#define SCAN_REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF \
( \
resolve, "$self, target, /, ctx=None, scope=None", \
- METH_VARARGS, py_registered_item, \
+ METH_VARARGS, py_scan_registered_item, \
"Resolve a name into a scan item." \
"\n" \
"The *target* name is the only mandatory parameter and has to point"\
@@ -137,9 +532,9 @@ static PyObject *py_registered_item_resolve(PyObject *self, PyObject *args)
convert_to_scan_context, &ctx);
if (!ret) return NULL;
- item = G_REGISTERED_ITEM(pygobject_get(self));
+ item = G_SCAN_REGISTERED_ITEM(pygobject_get(self));
- status = g_registered_item_resolve(item, target, ctx, scope, &resolved);
+ status = g_scan_registered_item_resolve(item, target, ctx, scope, &resolved);
if (!status)
{
@@ -178,23 +573,23 @@ static PyObject *py_registered_item_resolve(PyObject *self, PyObject *args)
* *
******************************************************************************/
-static PyObject *py_registered_item_get_name(PyObject *self, void *closure)
+static PyObject *py_scan_registered_item_get_name(PyObject *self, void *closure)
{
PyObject *result; /* Décompte à retourner */
- GRegisteredItem *item; /* Version native */
+ GScanRegisteredItem *item; /* Version native */
char *name; /* Désignation à convertir */
-#define REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+#define SCAN_REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL \
( \
- name, py_registered_item, \
+ name, py_scan_registered_item, \
"Name linked to the registered item.\n" \
"\n" \
"The result should be a string, or *None* for the root namespace." \
)
- item = G_REGISTERED_ITEM(pygobject_get(self));
+ item = G_SCAN_REGISTERED_ITEM(pygobject_get(self));
- name = g_registered_item_get_name(item);
+ name = g_scan_registered_item_get_name(item);
if (name == NULL)
{
@@ -224,38 +619,42 @@ static PyObject *py_registered_item_get_name(PyObject *self, void *closure)
* *
******************************************************************************/
-PyTypeObject *get_python_registered_item_type(void)
+PyTypeObject *get_python_scan_registered_item_type(void)
{
- static PyMethodDef py_registered_item_methods[] = {
- REGISTERED_ITEM_RESOLVE_METHOD,
+ static PyMethodDef py_scan_registered_item_methods[] = {
+ SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER,
+ SCAN_REGISTERED_ITEM_REDUCE_WRAPPER,
+ SCAN_REGISTERED_ITEM_CALL_WRAPPER,
+ SCAN_REGISTERED_ITEM_RESOLVE_METHOD,
{ NULL }
};
- static PyGetSetDef py_registered_item_getseters[] = {
- REGISTERED_ITEM_NAME_ATTRIB,
+ static PyGetSetDef py_scan_registered_item_getseters[] = {
+ SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER,
+ SCAN_REGISTERED_ITEM_NAME_ATTRIB,
{ NULL }
};
- static PyTypeObject py_registered_item_type = {
+ static PyTypeObject py_scan_registered_item_type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pychrysalide.analysis.scan.RegisteredItem",
+ .tp_name = "pychrysalide.analysis.scan.ScanRegisteredItem",
.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,
+ .tp_doc = SCAN_REGISTERED_ITEM_DOC,
- .tp_methods = py_registered_item_methods,
- .tp_getset = py_registered_item_getseters,
+ .tp_methods = py_scan_registered_item_methods,
+ .tp_getset = py_scan_registered_item_getseters,
- .tp_init = py_registered_item_init,
- .tp_new = py_registered_item_new,
+ .tp_init = py_scan_registered_item_init,
+ .tp_new = py_scan_registered_item_new,
};
- return &py_registered_item_type;
+ return &py_scan_registered_item_type;
}
@@ -264,7 +663,7 @@ PyTypeObject *get_python_registered_item_type(void)
* *
* Paramètres : - *
* *
-* Description : Prend en charge l'objet 'pychrysalide...scan.RegisteredItem'.*
+* Description : Prend en charge l'objet 'pychrysalide...ScanRegisteredItem'. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -272,13 +671,13 @@ PyTypeObject *get_python_registered_item_type(void)
* *
******************************************************************************/
-bool ensure_python_registered_item_is_registered(void)
+bool ensure_python_scan_registered_item_is_registered(void)
{
- PyTypeObject *type; /* Type Python 'RegisteredItem' */
+ PyTypeObject *type; /* Type 'ScanRegisteredItem' */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- type = get_python_registered_item_type();
+ type = get_python_scan_registered_item_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
@@ -286,7 +685,7 @@ bool ensure_python_registered_item_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_REGISTERED_ITEM, type))
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REGISTERED_ITEM, type))
return false;
}
@@ -309,11 +708,11 @@ bool ensure_python_registered_item_is_registered(void)
* *
******************************************************************************/
-int convert_to_registered_item(PyObject *arg, void *dst)
+int convert_to_scan_registered_item(PyObject *arg, void *dst)
{
int result; /* Bilan à retourner */
- result = PyObject_IsInstance(arg, (PyObject *)get_python_registered_item_type());
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_registered_item_type());
switch (result)
{
@@ -327,7 +726,7 @@ int convert_to_registered_item(PyObject *arg, void *dst)
break;
case 1:
- *((GRegisteredItem **)dst) = G_REGISTERED_ITEM(pygobject_get(arg));
+ *((GScanRegisteredItem **)dst) = G_SCAN_REGISTERED_ITEM(pygobject_get(arg));
break;
default: