X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;ds=sidebyside;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