diff options
Diffstat (limited to 'plugins/pychrysalide/arch')
| -rw-r--r-- | plugins/pychrysalide/arch/instruction.c | 126 | ||||
| -rw-r--r-- | plugins/pychrysalide/arch/operand.c | 298 | 
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 }      }; | 
