예제 #1
0
/**
 * Get the value of a Python dictionary item, returned as a newly
 * allocated char *.
 *
 * @param py_obj The dictionary to probe.
 * @param key Key of the item to retrieve.
 * @param outstr Pointer to char * storage to be filled in.
 *
 * @return SRD_OK upon success, a (negative) error code otherwise.
 *         The 'outstr' argument points to a malloc()ed string upon success.
 *
 * @private
 */
SRD_PRIV int py_dictitem_as_str(const PyObject *py_obj, const char *key,
				char **outstr)
{
	PyObject *py_value;
	int ret;

	if (!PyDict_Check((PyObject *)py_obj)) {
		srd_dbg("Object is a %s, not a dictionary.",
			Py_TYPE((PyObject *)py_obj)->tp_name);
		return SRD_ERR_PYTHON;
	}

	if (!(py_value = PyDict_GetItemString((PyObject *)py_obj, key))) {
		srd_dbg("Dictionary has no attribute '%s'.", key);
		return SRD_ERR_PYTHON;
	}

	if (!PyUnicode_Check(py_value)) {
		srd_dbg("Dictionary value for %s should be a string, but is "
			"a %s.", key, Py_TYPE(py_value)->tp_name);
		return SRD_ERR_PYTHON;
	}

	ret = py_str_as_str(py_value, outstr);

	return ret;
}
예제 #2
0
/**
 * Get the value of a Python object's attribute, returned as a newly
 * allocated char *.
 *
 * @param py_obj The object to probe.
 * @param attr Name of the attribute to retrieve.
 * @param outstr ptr to char * storage to be filled in.
 *
 * @return SRD_OK upon success, a (negative) error code otherwise.
 *         The 'outstr' argument points to a malloc()ed string upon success.
 *
 * @private
 */
SRD_PRIV int py_attr_as_str(const PyObject *py_obj, const char *attr,
			    char **outstr)
{
	PyObject *py_str;
	int ret;

	if (!PyObject_HasAttrString((PyObject *)py_obj, attr)) {
		srd_dbg("%s object has no attribute '%s'.",
			Py_TYPE(py_obj)->tp_name, attr);
		return SRD_ERR_PYTHON;
	}

	if (!(py_str = PyObject_GetAttrString((PyObject *)py_obj, attr))) {
		srd_exception_catch("");
		return SRD_ERR_PYTHON;
	}

	if (!PyUnicode_Check(py_str)) {
		srd_dbg("%s attribute should be a string, but is a %s.",
			attr, Py_TYPE(py_str)->tp_name);
		Py_DecRef(py_str);
		return SRD_ERR_PYTHON;
	}

	ret = py_str_as_str(py_str, outstr);
	Py_DecRef(py_str);

	return ret;
}
예제 #3
0
/**
 * Add an additional search directory for the protocol decoders.
 *
 * The specified directory is prepended (not appended!) to Python's sys.path,
 * in order to search for sigrok protocol decoders in the specified
 * directories first, and in the generic Python module directories (and in
 * the current working directory) last. This avoids conflicts if there are
 * Python modules which have the same name as a sigrok protocol decoder in
 * sys.path or in the current working directory.
 *
 * @param path Path to the directory containing protocol decoders which shall
 *             be added to the Python sys.path, or NULL.
 *
 * @return SRD_OK upon success, a (negative) error code otherwise.
 */
SRD_PRIV int srd_decoder_searchpath_add(const char *path)
{
	PyObject *py_cur_path, *py_item;
	GString *new_path;
	int wc_len, i;
	wchar_t *wc_new_path;
	char *item;

	srd_dbg("Adding '%s' to module path.", path);

	new_path = g_string_sized_new(256);
	g_string_assign(new_path, g_strdup(path));
	py_cur_path = PySys_GetObject("path");
	for (i = 0; i < PyList_Size(py_cur_path); i++) {
		g_string_append(new_path, g_strdup(G_SEARCHPATH_SEPARATOR_S));
		py_item = PyList_GetItem(py_cur_path, i);
		if (!PyUnicode_Check(py_item))
			/* Shouldn't happen. */
			continue;
		if (py_str_as_str(py_item, &item) != SRD_OK)
			continue;
		g_string_append(new_path, item);
	}

	/* Convert to wide chars. */
	wc_len = sizeof(wchar_t) * (new_path->len + 1);
	if (!(wc_new_path = g_try_malloc(wc_len))) {
		srd_dbg("malloc failed");
		return SRD_ERR_MALLOC;
	}
	mbstowcs(wc_new_path, new_path->str, wc_len);
	PySys_SetPath(wc_new_path);
	g_string_free(new_path, TRUE);
	g_free(wc_new_path);

//#ifdef _WIN32
//	gchar **splitted;
//
//	/*
//	 * On Windows/MinGW, Python's sys.path needs entries of the form
//	 * 'C:\\foo\\bar' instead of '/foo/bar'.
//	 */
//
//	splitted = g_strsplit(DECODERS_DIR, "/", 0);
//	path = g_build_pathv("\\\\", splitted);
//	g_strfreev(splitted);
//#else
//	path = g_strdup(DECODERS_DIR);
//#endif

	return SRD_OK;
}
예제 #4
0
파일: decoder.c 프로젝트: jeras/sigrok
/**
 * Return a protocol decoder's docstring.
 *
 * @param dec The loaded protocol decoder.
 *
 * @return A newly allocated buffer containing the protocol decoder's
 *         documentation. The caller is responsible for free'ing the buffer.
 */
SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec)
{
	PyObject *py_str;
	char *doc;

	if (!PyObject_HasAttrString(dec->py_mod, "__doc__"))
		return NULL;

	if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) {
		srd_exception_catch("");
		return NULL;
	}

	doc = NULL;
	if (py_str != Py_None)
		py_str_as_str(py_str, &doc);
	Py_DecRef(py_str);

	return doc;
}
예제 #5
0
/**
 * Add an additional search directory for the protocol decoders.
 *
 * The specified directory is prepended (not appended!) to Python's sys.path,
 * in order to search for sigrok protocol decoders in the specified
 * directories first, and in the generic Python module directories (and in
 * the current working directory) last. This avoids conflicts if there are
 * Python modules which have the same name as a sigrok protocol decoder in
 * sys.path or in the current working directory.
 *
 * @param path Path to the directory containing protocol decoders which shall
 *             be added to the Python sys.path, or NULL.
 *
 * @return SRD_OK upon success, a (negative) error code otherwise.
 *
 * @private
 *
 * @since 0.1.0
 */
SRD_PRIV int srd_decoder_searchpath_add(const char *path)
{
	PyObject *py_cur_path, *py_item;
	GString *new_path;
	int wc_len, i;
	wchar_t *wc_new_path;
	char *item;

	srd_dbg("Adding '%s' to module path.", path);

	new_path = g_string_sized_new(256);
	g_string_assign(new_path, path);
	py_cur_path = PySys_GetObject("path");
	for (i = 0; i < PyList_Size(py_cur_path); i++) {
		g_string_append(new_path, G_SEARCHPATH_SEPARATOR_S);
		py_item = PyList_GetItem(py_cur_path, i);
		if (!PyUnicode_Check(py_item))
			/* Shouldn't happen. */
			continue;
		if (py_str_as_str(py_item, &item) != SRD_OK)
			continue;
		g_string_append(new_path, item);
		g_free(item);
	}

	/* Convert to wide chars. */
	wc_len = sizeof(wchar_t) * (new_path->len + 1);
	if (!(wc_new_path = g_try_malloc(wc_len))) {
		srd_dbg("malloc failed");
		return SRD_ERR_MALLOC;
	}
	mbstowcs(wc_new_path, new_path->str, wc_len);
	PySys_SetPath(wc_new_path);
	g_string_free(new_path, TRUE);
	g_free(wc_new_path);

	return SRD_OK;
}
예제 #6
0
/** @private */
SRD_PRIV void srd_exception_catch(const char *format, ...)
{
	PyObject *etype, *evalue, *etb, *py_str;
	PyTracebackObject *py_tb;
	GString *msg;
	va_list args;
	char *ename, *str, *tracestr;

	if (!PyErr_Occurred())
		/* Nothing is wrong. */
		return;

	PyErr_Fetch(&etype, &evalue, &etb);
	PyErr_NormalizeException(&etype, &evalue, &etb);

	if (!(py_str = PyObject_Str(evalue))) {
		/* Shouldn't happen. */
		srd_dbg("Failed to convert exception value to string.");
		return;
	}

	/* Send the exception error message(s) to srd_err(). */
	if (evalue)
		ename = (char *)Py_TYPE(evalue)->tp_name;
	else
		/* Can be NULL. */
		ename = "(unknown exception)";

	msg = g_string_sized_new(128);
	g_string_append(msg, ename);
	g_string_append(msg, ": ");
	va_start(args, format);
	g_string_append_vprintf(msg, format, args);
	va_end(args);
	py_str_as_str(py_str, &str);
	g_string_append(msg, str);
	Py_DecRef(py_str);
	srd_err(msg->str);

	/* Send a more precise error location to srd_dbg(), if we have it. */
	if (etb && etb != Py_None) {
		tracestr = NULL;
		py_tb = (PyTracebackObject *)etb;
		py_str = PyUnicode_FromFormat("%U:%d in %U",
					py_tb->tb_frame->f_code->co_filename,
					py_tb->tb_frame->f_lineno,
					py_tb->tb_frame->f_code->co_name);
		py_str_as_str(py_str, &tracestr);
		Py_DecRef(py_str);
		g_string_printf(msg, "%s in %s: %s", ename, tracestr, str);
		srd_dbg(msg->str);
		g_free(tracestr);
	}
	g_free(str);
	g_string_free(msg, TRUE);

	Py_XDECREF(etype);
	Py_XDECREF(evalue);
	Py_XDECREF(etb);

	/* Just in case. */
	PyErr_Clear();
}
예제 #7
0
/**
 * Set one or more options in a decoder instance.
 *
 * Handled options are removed from the hash.
 *
 * @param di Decoder instance.
 * @param options A GHashTable of options to set.
 *
 * @return SRD_OK upon success, a (negative) error code otherwise.
 *
 * @since 0.1.0
 */
SRD_API int srd_inst_option_set(struct srd_decoder_inst *di,
		GHashTable *options)
{
	PyObject *py_dec_options, *py_dec_optkeys, *py_di_options, *py_optval;
	PyObject *py_optlist, *py_classval;
	Py_UNICODE *py_ustr;
	GVariant *value;
	unsigned long long int val_ull;
	gint64 val_int;
	int num_optkeys, ret, size, i;
	const char *val_str;
	char *dbg, *key;

	if (!di) {
		srd_err("Invalid decoder instance.");
		return SRD_ERR_ARG;
	}

	if (!options) {
		srd_err("Invalid options GHashTable.");
		return SRD_ERR_ARG;
	}

	if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) {
		/* Decoder has no options. */
		if (g_hash_table_size(options) == 0) {
			/* No options provided. */
			return SRD_OK;
		} else {
			srd_err("Protocol decoder has no options.");
			return SRD_ERR_ARG;
		}
		return SRD_OK;
	}

	ret = SRD_ERR_PYTHON;
	key = NULL;
	py_dec_options = py_dec_optkeys = py_di_options = py_optval = NULL;
	py_optlist = py_classval = NULL;
	py_dec_options = PyObject_GetAttrString(di->decoder->py_dec, "options");

	/* All of these are synthesized objects, so they're good. */
	py_dec_optkeys = PyDict_Keys(py_dec_options);
	num_optkeys = PyList_Size(py_dec_optkeys);

	/*
	 * The 'options' dictionary is a class variable, but we need to
	 * change it. Changing it directly will affect the entire class,
	 * so we need to create a new object for it, and populate that
	 * instead.
	 */
	if (!(py_di_options = PyObject_GetAttrString(di->py_inst, "options")))
		goto err_out;
	Py_DECREF(py_di_options);
	py_di_options = PyDict_New();
	PyObject_SetAttrString(di->py_inst, "options", py_di_options);
	for (i = 0; i < num_optkeys; i++) {
		/* Get the default class value for this option. */
		py_str_as_str(PyList_GetItem(py_dec_optkeys, i), &key);
		if (!(py_optlist = PyDict_GetItemString(py_dec_options, key)))
			goto err_out;
		if (!(py_classval = PyList_GetItem(py_optlist, 1)))
			goto err_out;
		if (!PyUnicode_Check(py_classval) && !PyLong_Check(py_classval)) {
			srd_err("Options of type %s are not yet supported.",
				Py_TYPE(py_classval)->tp_name);
			goto err_out;
		}

		if ((value = g_hash_table_lookup(options, key))) {
			dbg = g_variant_print(value, TRUE);
			srd_dbg("got option '%s' = %s", key, dbg);
			g_free(dbg);
			/* An override for this option was provided. */
			if (PyUnicode_Check(py_classval)) {
				if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
					srd_err("Option '%s' requires a string value.", key);
					goto err_out;
				}
				val_str = g_variant_get_string(value, NULL);
				if (!(py_optval = PyUnicode_FromString(val_str))) {
					/* Some UTF-8 encoding error. */
					PyErr_Clear();
					srd_err("Option '%s' requires a UTF-8 string value.", key);
					goto err_out;
				}
			} else if (PyLong_Check(py_classval)) {
				if (!g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)) {
					srd_err("Option '%s' requires an integer value.", key);
					goto err_out;
				}
				val_int = g_variant_get_int64(value);
				if (!(py_optval = PyLong_FromLong(val_int))) {
					/* ValueError Exception */
					PyErr_Clear();
					srd_err("Option '%s' has invalid integer value.", key);
					goto err_out;
				}
			}
			g_hash_table_remove(options, key);
		} else {
			/* Use the class default for this option. */
			if (PyUnicode_Check(py_classval)) {
				/* Make a brand new copy of the string. */
				py_ustr = PyUnicode_AS_UNICODE(py_classval);
				size = PyUnicode_GET_SIZE(py_classval);
				py_optval = PyUnicode_FromUnicode(py_ustr, size);
			} else if (PyLong_Check(py_classval)) {
				/* Make a brand new copy of the integer. */
				val_ull = PyLong_AsUnsignedLongLong(py_classval);
				if (val_ull == (unsigned long long)-1) {
					/* OverFlowError exception */
					PyErr_Clear();
					srd_err("Invalid integer value for %s: "
						"expected integer.", key);
					goto err_out;
				}
				if (!(py_optval = PyLong_FromUnsignedLongLong(val_ull)))
					goto err_out;
			}
		}

		/*
		 * If we got here, py_optval holds a known good new reference
		 * to the instance option to set.
		 */
		if (PyDict_SetItemString(py_di_options, key, py_optval) == -1)
			goto err_out;
		g_free(key);
		key = NULL;
	}

	ret = SRD_OK;

err_out:
	Py_XDECREF(py_di_options);
	Py_XDECREF(py_dec_optkeys);
	Py_XDECREF(py_dec_options);
	g_free(key);
	if (PyErr_Occurred()) {
		srd_exception_catch("Stray exception in srd_inst_option_set().");
		ret = SRD_ERR_PYTHON;
	}

	return ret;
}
예제 #8
0
/**
 * Set one or more options in a decoder instance.
 *
 * Handled options are removed from the hash.
 *
 * @param di Decoder instance.
 * @param options A GHashTable of options to set.
 *
 * @return SRD_OK upon success, a (negative) error code otherwise.
 */
SRD_API int srd_inst_option_set(struct srd_decoder_inst *di,
				GHashTable *options)
{
	PyObject *py_dec_options, *py_dec_optkeys, *py_di_options, *py_optval;
	PyObject *py_optlist, *py_classval;
	Py_UNICODE *py_ustr;
	unsigned long long int val_ull;
	int num_optkeys, ret, size, i;
	char *key, *value;

	if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) {
		/* Decoder has no options. */
		if (g_hash_table_size(options) == 0) {
			/* No options provided. */
			return SRD_OK;
		} else {
			srd_err("Protocol decoder has no options.");
			return SRD_ERR_ARG;
		}
		return SRD_OK;
	}

	ret = SRD_ERR_PYTHON;
	key = NULL;
	py_dec_options = py_dec_optkeys = py_di_options = py_optval = NULL;
	py_optlist = py_classval = NULL;
	py_dec_options = PyObject_GetAttrString(di->decoder->py_dec, "options");

	/* All of these are synthesized objects, so they're good. */
	py_dec_optkeys = PyDict_Keys(py_dec_options);
	num_optkeys = PyList_Size(py_dec_optkeys);
	if (!(py_di_options = PyObject_GetAttrString(di->py_inst, "options")))
		goto err_out;
	for (i = 0; i < num_optkeys; i++) {
		/* Get the default class value for this option. */
		py_str_as_str(PyList_GetItem(py_dec_optkeys, i), &key);
		if (!(py_optlist = PyDict_GetItemString(py_dec_options, key)))
			goto err_out;
		if (!(py_classval = PyList_GetItem(py_optlist, 1)))
			goto err_out;
		if (!PyUnicode_Check(py_classval) && !PyLong_Check(py_classval)) {
			srd_err("Options of type %s are not yet supported.",
				Py_TYPE(py_classval)->tp_name);
			goto err_out;
		}

		if ((value = g_hash_table_lookup(options, key))) {
			/* An override for this option was provided. */
			if (PyUnicode_Check(py_classval)) {
				if (!(py_optval = PyUnicode_FromString(value))) {
					/* Some UTF-8 encoding error. */
					PyErr_Clear();
					goto err_out;
				}
			} else if (PyLong_Check(py_classval)) {
				if (!(py_optval = PyLong_FromString(value, NULL, 0))) {
					/* ValueError Exception */
					PyErr_Clear();
					srd_err("Option %s has invalid value "
						"%s: expected integer.",
						key, value);
					goto err_out;
				}
			}
			g_hash_table_remove(options, key);
		} else {
			/* Use the class default for this option. */
			if (PyUnicode_Check(py_classval)) {
				/* Make a brand new copy of the string. */
				py_ustr = PyUnicode_AS_UNICODE(py_classval);
				size = PyUnicode_GET_SIZE(py_classval);
				py_optval = PyUnicode_FromUnicode(py_ustr, size);
			} else if (PyLong_Check(py_classval)) {
				/* Make a brand new copy of the integer. */
				val_ull = PyLong_AsUnsignedLongLong(py_classval);
				if (val_ull == (unsigned long long)-1) {
					/* OverFlowError exception */
					PyErr_Clear();
					srd_err("Invalid integer value for %s: "
						"expected integer.", key);
					goto err_out;
				}
				if (!(py_optval = PyLong_FromUnsignedLongLong(val_ull)))
					goto err_out;
			}
		}

		/*
		 * If we got here, py_optval holds a known good new reference
		 * to the instance option to set.
		 */
		if (PyDict_SetItemString(py_di_options, key, py_optval) == -1)
			goto err_out;
	}

	ret = SRD_OK;

err_out:
	Py_XDECREF(py_optlist);
	Py_XDECREF(py_di_options);
	Py_XDECREF(py_dec_optkeys);
	Py_XDECREF(py_dec_options);
	g_free(key);
	if (PyErr_Occurred())
		srd_exception_catch("Stray exception in srd_inst_option_set().");

	return ret;
}