X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=decoder.c;h=e50345f21566d2bd41bad103f6d1eab8fb45aeb6;hb=201a85a8ea071d37f4fda2668c0a1c488d852f4e;hp=71e9122181324fad0325314ddbf78eb75f2fc1a6;hpb=5c0c9cb3a78be20d98f81cff1405bbf2c927384e;p=libsigrokdecode.git diff --git a/decoder.c b/decoder.c index 71e9122..e50345f 100644 --- a/decoder.c +++ b/decoder.c @@ -18,9 +18,9 @@ * along with this program. If not, see . */ -#include "config.h" -#include "libsigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */ -#include "libsigrokdecode-internal.h" +#include +#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */ +#include "libsigrokdecode.h" #include /** @@ -66,7 +66,7 @@ static gboolean srd_check_init(void) /** * Returns the list of supported/loaded protocol decoders. * - * This is a GSList containing the names of the decoders as strings. + * This is a GSList of pointers to struct srd_decoder items. * * @return List of decoders, NULL if none are supported or loaded. * @@ -132,11 +132,7 @@ static int get_channels(const struct srd_decoder *d, const char *attr, break; } - if (!(pdch = g_try_malloc(sizeof(struct srd_channel)))) { - srd_err("Failed to g_malloc() struct srd_channel."); - ret = SRD_ERR_MALLOC; - break; - } + pdch = g_malloc(sizeof(struct srd_channel)); if ((py_dictitem_as_str(py_entry, "id", &pdch->id)) != SRD_OK) { ret = SRD_ERR_PYTHON; @@ -191,8 +187,8 @@ static int get_options(struct srd_decoder *d) return SRD_ERR_PYTHON; } if (!(py_val = PyDict_GetItemString(py_opt, "id"))) { - srd_err("Protocol decoder %s option %d has no " - "id.", d->name); + srd_err("Protocol decoder %s option %zd has no " + "id.", d->name, opt); return SRD_ERR_PYTHON; } o = g_malloc0(sizeof(struct srd_decoder_option)); @@ -229,8 +225,7 @@ static int get_options(struct srd_decoder *d) o->def = g_variant_new_double(dval); } else { srd_err("Protocol decoder %s option 'default' has " - "value of unsupported type '%s'.", d->name, - Py_TYPE(py_default)->tp_name); + "value of unsupported type.", d->name); return SRD_ERR_PYTHON; } g_variant_ref_sink(o->def); @@ -331,17 +326,13 @@ SRD_API int srd_decoder_load(const char *module_name) py_basedec = py_method = py_attr = NULL; - if (!(d = g_try_malloc0(sizeof(struct srd_decoder)))) { - srd_dbg("Failed to g_malloc() struct srd_decoder."); - ret = SRD_ERR_MALLOC; - goto err_out; - } + d = g_malloc0(sizeof(struct srd_decoder)); ret = SRD_ERR_PYTHON; /* Import the Python module. */ if (!(d->py_mod = PyImport_ImportModule(module_name))) { - srd_exception_catch("Import of '%s' failed.", module_name); + srd_exception_catch("Import of '%s' failed", module_name); goto err_out; } @@ -367,7 +358,7 @@ SRD_API int srd_decoder_load(const char *module_name) Py_CLEAR(py_basedec); /* - * Check that thіs decoder has the correct PD API version. + * Check that this decoder has the correct PD API version. * PDs of different API versions are incompatible and cannot work. */ py_long = PyObject_GetAttrString(d->py_dec, "api_version"); @@ -384,7 +375,7 @@ SRD_API int srd_decoder_load(const char *module_name) goto err_out; } py_method = PyObject_GetAttrString(d->py_dec, "start"); - if (!PyFunction_Check(py_method)) { + if (!PyCallable_Check(py_method)) { srd_err("Protocol decoder %s Decoder class attribute 'start' " "is not a method.", module_name); goto err_out; @@ -398,7 +389,7 @@ SRD_API int srd_decoder_load(const char *module_name) goto err_out; } py_method = PyObject_GetAttrString(d->py_dec, "decode"); - if (!PyFunction_Check(py_method)) { + if (!PyCallable_Check(py_method)) { srd_err("Protocol decoder %s Decoder class attribute 'decode' " "is not a method.", module_name); goto err_out; @@ -596,7 +587,7 @@ SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec) return NULL; if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) { - srd_exception_catch(""); + srd_exception_catch("Failed to get docstring"); return NULL; } @@ -687,14 +678,98 @@ SRD_API int srd_decoder_unload(struct srd_decoder *dec) return SRD_OK; } +static void srd_decoder_load_all_zip_path(char *path) +{ + PyObject *zipimport_mod, *zipimporter_class, *zipimporter; + PyObject *prefix_obj, *files, *key, *value, *set, *modname; + Py_ssize_t pos = 0; + char *prefix; + size_t prefix_len; + + set = files = prefix_obj = zipimporter = zipimporter_class = NULL; + + zipimport_mod = PyImport_ImportModule("zipimport"); + if (zipimport_mod == NULL) + goto err_out; + + zipimporter_class = PyObject_GetAttrString(zipimport_mod, "zipimporter"); + if (zipimporter_class == NULL) + goto err_out; + + zipimporter = PyObject_CallFunction(zipimporter_class, "s", path); + if (zipimporter == NULL) + goto err_out; + + prefix_obj = PyObject_GetAttrString(zipimporter, "prefix"); + if (prefix_obj == NULL) + goto err_out; + + files = PyObject_GetAttrString(zipimporter, "_files"); + if (files == NULL) + goto err_out; + + set = PySet_New(NULL); + if (set == NULL) + goto err_out; + + if (py_str_as_str(prefix_obj, &prefix) != SRD_OK) + goto err_out; + + prefix_len = strlen(prefix); + + while (PyDict_Next(files, &pos, &key, &value)) { + char *path, *slash; + if (py_str_as_str(key, &path) == SRD_OK) { + if (strlen(path) > prefix_len && + !memcmp(path, prefix, prefix_len) && + (slash = strchr(path+prefix_len, '/'))) { + modname = + PyUnicode_FromStringAndSize(path+prefix_len, + slash-(path+prefix_len)); + if (modname == NULL) { + PyErr_Clear(); + } else { + PySet_Add(set, modname); + Py_XDECREF(modname); + } + } + free(path); + } + } + + free(prefix); + + while ((modname = PySet_Pop(set))) { + char *modname_str; + if (py_str_as_str(modname, &modname_str) == SRD_OK) { + /* The directory name is the module name (e.g. "i2c"). */ + srd_decoder_load(modname_str); + free(modname_str); + } + Py_XDECREF(modname); + } + +err_out: + Py_XDECREF(set); + Py_XDECREF(files); + Py_XDECREF(prefix_obj); + Py_XDECREF(zipimporter); + Py_XDECREF(zipimporter_class); + Py_XDECREF(zipimport_mod); + PyErr_Clear(); +} + static void srd_decoder_load_all_path(char *path) { GDir *dir; const gchar *direntry; - if (!(dir = g_dir_open(path, 0, NULL))) + if (!(dir = g_dir_open(path, 0, NULL))) { /* Not really fatal */ + /* Try zipimport method too */ + srd_decoder_load_all_zip_path(path); return; + } /* This ignores errors returned by srd_decoder_load(). That * function will have logged the cause, but in any case we