From: Bert Vermeulen Date: Mon, 23 Jan 2012 01:20:51 +0000 (+0100) Subject: srd: add python exception catcher, which routes to srd_err() and srd_dbg() X-Git-Tag: libsigrokdecode-0.1.0~108 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=ec871a279893cfe0ab378eddc0a9f9bcccc44925;p=libsigrokdecode.git srd: add python exception catcher, which routes to srd_err() and srd_dbg() --- diff --git a/Makefile.am b/Makefile.am index d7e33c2..fd5e004 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 index 0000000..07ffab3 --- /dev/null +++ b/exception.c @@ -0,0 +1,95 @@ +/* + * This file is part of the sigrok project. + * + * Copyright (C) 2012 Bert Vermeulen + * + * 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 . + */ + +#include "sigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */ +#include "sigrokdecode-internal.h" +#include "config.h" +#include +#include +#include /* 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; +} + + diff --git a/sigrokdecode.h b/sigrokdecode.h index 70652a4..dfddb13 100644 --- a/sigrokdecode.h +++ b/sigrokdecode.h @@ -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);