--- /dev/null
+/*
+ * This file is part of the sigrok project.
+ *
+ * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
+#include "sigrokdecode-internal.h"
+#include "config.h"
+#include <stdarg.h>
+#include <glib.h>
+#include <frameobject.h> /* Python header not pulled in by default. */
+
+
+void catch_exception(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("srd: failed to convert exception value to string");
+ return;
+ }
+
+ msg = g_string_sized_new(128);
+ va_start(args, format);
+ g_string_vprintf(msg, format, args);
+ va_end(args);
+
+ /* Can be NULL. */
+ if (evalue)
+ ename = (char *)Py_TYPE(evalue)->tp_name;
+ else
+ ename = "(unknown exception)";
+
+ /* Send the exception error message(s) to srd_err(). */
+ py_str_as_str(py_str, &str);
+ g_string_append(msg, ename);
+ g_string_append(msg, ": ");
+ 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, "srd: %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();
+
+ return;
+}
+
+