X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=decode.c;h=97a13c462ad3bbe10b270d86e005874565d92b06;hp=0cceee14a0d7643f33ec44140c7759f0476cfccd;hb=53bec0cfaef9ce8c646deee7d9ba6340137713a1;hpb=036e6f672169c63fb304f3842667e3a09879b512 diff --git a/decode.c b/decode.c index 0cceee1..97a13c4 100644 --- a/decode.c +++ b/decode.c @@ -39,14 +39,17 @@ GSList *list_pds = NULL; * * Check the Python/C API docs for what type of reference a function returns. * - * - If it returns a "new reference", you're responsible to Py_DECREF() it. + * - If it returns a "new reference", you're responsible to Py_XDECREF() it. * - * - If it returns a "borrowed reference", you MUST NOT Py_DECREF() it. + * - If it returns a "borrowed reference", you MUST NOT Py_XDECREF() it. * * - If a function "steals" a reference, you no longer are responsible for - * Py_DECREF()ing it (someone else will do it for you at some point). + * Py_XDECREF()ing it (someone else will do it for you at some point). */ +static int sigrokdecode_load_decoder(const char *name, + struct sigrokdecode_decoder **dec); + /** * Initialize libsigrokdecode. * @@ -56,7 +59,9 @@ int sigrokdecode_init(void) { DIR *dir; struct dirent *dp; - char *tmp; + char *decodername; + struct sigrokdecode_decoder *dec; + int ret; /* Py_Initialize() returns void and usually cannot fail. */ Py_Initialize(); @@ -73,9 +78,18 @@ int sigrokdecode_init(void) while ((dp = readdir(dir)) != NULL) { if (!g_str_has_suffix(dp->d_name, ".py")) continue; - /* For now use the filename (without .py) as decoder name. */ - if ((tmp = g_strndup(dp->d_name, strlen(dp->d_name) - 3))) - list_pds = g_slist_append(list_pds, tmp); + + /* Decoder name == filename (without .py suffix). */ + decodername = g_strndup(dp->d_name, strlen(dp->d_name) - 3); + + /* TODO: Error handling. */ + dec = malloc(sizeof(struct sigrokdecode_decoder)); + + /* Load the decoder. */ + ret = sigrokdecode_load_decoder(decodername, &dec); + + /* Append it to the list of supported/loaded decoders. */ + list_pds = g_slist_append(list_pds, dec); } closedir(dir); @@ -94,6 +108,26 @@ GSList *sigrokdecode_list_decoders(void) return list_pds; } +/** + * Get the decoder with the specified ID. + * + * @param id The ID string of the decoder to return. + * @return The decoder with the specified ID, or NULL if not found. + */ +struct sigrokdecode_decoder *sigrokdecode_get_decoder_by_id(const char *id) +{ + GSList *l; + struct sigrokdecode_decoder *dec; + + for (l = sigrokdecode_list_decoders(); l; l = l->next) { + dec = l->data; + if (!strcmp(dec->id, id)) + return dec; + } + + return NULL; +} + /** * Helper function to handle Python strings. * @@ -107,14 +141,12 @@ static int h_str(PyObject *py_res, PyObject *py_func, PyObject *py_mod, { PyObject *py_str; char *str; + int ret; py_str = PyMapping_GetItemString(py_res, (char *)key); if (!py_str || !PyString_Check(py_str)) { - if (PyErr_Occurred()) - PyErr_Print(); /* Returns void. */ - Py_DECREF(py_func); - Py_DECREF(py_mod); - return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ + ret = SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ + goto err_h_decref_func; } /* @@ -123,26 +155,29 @@ static int h_str(PyObject *py_res, PyObject *py_func, PyObject *py_mod, * must not be free()'d. */ if (!(str = PyString_AsString(py_str))) { - if (PyErr_Occurred()) - PyErr_Print(); /* Returns void. */ - Py_DECREF(py_str); - Py_DECREF(py_func); - Py_DECREF(py_mod); - return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ + ret = SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ + goto err_h_decref_str; } if (!(*outstr = strdup(str))) { - if (PyErr_Occurred()) - PyErr_Print(); /* Returns void. */ - Py_DECREF(py_str); - Py_DECREF(py_func); - Py_DECREF(py_mod); - return SIGROKDECODE_ERR_MALLOC; + ret = SIGROKDECODE_ERR_MALLOC; + goto err_h_decref_str; } - Py_DECREF(py_str); + Py_XDECREF(py_str); return SIGROKDECODE_OK; + +err_h_decref_str: + Py_XDECREF(py_str); +err_h_decref_func: + Py_XDECREF(py_func); + Py_XDECREF(py_mod); + + if (PyErr_Occurred()) + PyErr_Print(); /* Returns void. */ + + return ret; } /** @@ -152,41 +187,33 @@ static int h_str(PyObject *py_res, PyObject *py_func, PyObject *py_mod, * * @return SIGROKDECODE_OK upon success, a (negative) error code otherwise. */ -int sigrokdecode_load_decoder(const char *name, +static int sigrokdecode_load_decoder(const char *name, struct sigrokdecode_decoder **dec) { struct sigrokdecode_decoder *d; - PyObject *py_name, *py_mod, *py_func, *py_res /* , *py_tuple */; + PyObject *py_mod, *py_func, *py_res /* , *py_tuple */; int r; - /* Get the name of the decoder module as Python string. */ - if (!(py_name = PyString_FromString(name))) { /* NEWREF */ - PyErr_Print(); /* Returns void. */ - return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ - } - /* "Import" the Python module. */ - if (!(py_mod = PyImport_Import(py_name))) { /* NEWREF */ + if (!(py_mod = PyImport_ImportModule(name))) { /* NEWREF */ PyErr_Print(); /* Returns void. */ - Py_DECREF(py_name); return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ } - Py_DECREF(py_name); /* Get the 'register' function name as Python callable object. */ py_func = PyObject_GetAttrString(py_mod, "register"); /* NEWREF */ if (!py_func || !PyCallable_Check(py_func)) { if (PyErr_Occurred()) PyErr_Print(); /* Returns void. */ - Py_DECREF(py_mod); + Py_XDECREF(py_mod); return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ } /* Call the 'register' function without arguments, get the result. */ if (!(py_res = PyObject_CallFunction(py_func, NULL))) { /* NEWREF */ PyErr_Print(); /* Returns void. */ - Py_DECREF(py_func); - Py_DECREF(py_mod); + Py_XDECREF(py_func); + Py_XDECREF(py_mod); return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ } @@ -204,15 +231,15 @@ int sigrokdecode_load_decoder(const char *name, d->py_mod = py_mod; - Py_DECREF(py_res); - Py_DECREF(py_func); + Py_XDECREF(py_res); + Py_XDECREF(py_func); /* Get the 'decode' function name as Python callable object. */ py_func = PyObject_GetAttrString(py_mod, "decode"); /* NEWREF */ if (!py_func || !PyCallable_Check(py_func)) { if (PyErr_Occurred()) PyErr_Print(); /* Returns void. */ - Py_DECREF(py_mod); + Py_XDECREF(py_mod); return SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ } @@ -259,9 +286,9 @@ int sigrokdecode_run_decoder(struct sigrokdecode_decoder *dec, /* TODO: Error handling. */ py_mod = dec->py_mod; - Py_INCREF(py_mod); + Py_XINCREF(py_mod); py_func = dec->py_func; - Py_INCREF(py_func); + Py_XINCREF(py_func); /* Create a Python tuple of size 1. */ if (!(py_args = PyTuple_New(1))) { /* NEWREF */ @@ -278,12 +305,12 @@ int sigrokdecode_run_decoder(struct sigrokdecode_decoder *dec, /* * IMPORTANT: PyTuple_SetItem() "steals" a reference to py_value! - * That means we are no longer responsible for Py_DECREF()'ing it. + * That means we are no longer responsible for Py_XDECREF()'ing it. * It will automatically be free'd when the 'py_args' tuple is free'd. */ if (PyTuple_SetItem(py_args, 0, py_value) != 0) { /* STEAL */ ret = SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ - Py_DECREF(py_value); /* TODO: Ref. stolen upon error? */ + Py_XDECREF(py_value); /* TODO: Ref. stolen upon error? */ goto err_run_decref_args; } @@ -295,20 +322,19 @@ int sigrokdecode_run_decoder(struct sigrokdecode_decoder *dec, if ((r = PyObject_AsCharBuffer(py_res, (const char **)outbuf, (Py_ssize_t *)outbuflen))) { ret = SIGROKDECODE_ERR_PYTHON; /* TODO: More specific error? */ - Py_DECREF(py_res); + Py_XDECREF(py_res); goto err_run_decref_args; } ret = SIGROKDECODE_OK; - Py_DECREF(py_res); + Py_XDECREF(py_res); err_run_decref_args: - Py_DECREF(py_args); + Py_XDECREF(py_args); err_run_decref_func: - Py_DECREF(py_func); -err_run_decref_mod: - Py_DECREF(py_mod); + Py_XDECREF(py_func); + Py_XDECREF(py_mod); if (PyErr_Occurred()) PyErr_Print(); /* Returns void. */