srd: add python exception catcher, which routes to srd_err() and srd_dbg()
authorBert Vermeulen <bert@biot.com>
Mon, 23 Jan 2012 01:20:51 +0000 (02:20 +0100)
committerBert Vermeulen <bert@biot.com>
Mon, 23 Jan 2012 03:53:32 +0000 (04:53 +0100)
Makefile.am
exception.c [new file with mode: 0644]
sigrokdecode.h

index d7e33c22b5f997fb0ce18e7a1a6daf53d8a2be1e..fd5e0046d79664d6301a45dbd734ccd94ca63049 100644 (file)
@@ -24,7 +24,7 @@ SUBDIRS = decoders
 
 lib_LTLIBRARIES = libsigrokdecode.la
 
-libsigrokdecode_la_SOURCES = controller.c decoder.c log.c util.c \
+libsigrokdecode_la_SOURCES = controller.c decoder.c log.c util.c exception.c \
        module_sigrokdecode.c type_decoder.c type_logic.c
 
 libsigrokdecode_la_CPPFLAGS = $(CPPFLAGS_PYTHON) \
diff --git a/exception.c b/exception.c
new file mode 100644 (file)
index 0000000..07ffab3
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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;
+}
+
+
index 70652a4f8cdcbf444c6316e5508a99d6b48a9112..dfddb1383aaddfcac9ee4e452aa192de9ab62ec4 100644 (file)
@@ -206,6 +206,9 @@ int srd_load_all_decoders(void);
 int srd_unload_all_decoders(void);
 char *srd_decoder_doc(struct srd_decoder *dec);
 
+/*--- exception.c -----------------------------------------------------------*/
+void catch_exception(const char *format, ...);
+
 /*--- util.c ----------------------------------------------------------------*/
 int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr);
 int py_dictitem_as_str(PyObject *py_obj, const char *key, char **outstr);