commit 3be483a237a79b833c31dc51a933ce59b783c1cb Author: Jonathan Schleifer Date: Wed May 14 23:20:55 2014 +0200 Initial import diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6f517cb --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +CC ?= clang +CFLAGS ?= -Weverything -std=c11 + +## For C11 +#CFLAGS += -DTRYCATCH_THREAD_LOCAL=_Thread_local +## For GCC / Clang +#CFLAGS += -DTRYCATCH_THREAD_LOCAL=__thread + +libtrycatch.a: trycatch.o + ar cr $@ $< + +example: example.o libtrycatch.a + ${CC} -L. -ltrycatch -o $@ $< diff --git a/README b/README new file mode 100644 index 0000000..5ffc959 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +This is a small library providing C++-like try/catch for C with almost +exactly the same syntax, see example.c. diff --git a/example.c b/example.c new file mode 100644 index 0000000..4fb79ab --- /dev/null +++ b/example.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "trycatch.h" + +int +main() +{ + try { + puts("try1"); + + try { + puts("try2"); + } catch (ex) { + (void)ex; + puts("this should not be called"); + } + + throw(5); + } catch (ex) { + printf("caught %d (should be 5)\n", ex); + } + + try { + throw(1); + return 1; + } catch (ex) { + (void)ex; + } + + return 0; +} diff --git a/trycatch.c b/trycatch.c new file mode 100644 index 0000000..555234a --- /dev/null +++ b/trycatch.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "trycatch.h" + +#ifndef TRYCATCH_THREAD_LOCAL +# define TRYCATCH_THREAD_LOCAL +#endif + +static TRYCATCH_THREAD_LOCAL struct trycatch_frame *trycatch_frames = NULL; + +struct trycatch_frame* +trycatch_frame_push() +{ + struct trycatch_frame *frame; + + if ((frame = malloc(sizeof(*frame))) == NULL) { + fputs("Not enough memory to allocate exception frame!\n", + stderr); + abort(); + } + + frame->prev = trycatch_frames; + trycatch_frames = frame; + + return frame; +} + +void +trycatch_frame_pop() +{ + struct trycatch_frame *frame = trycatch_frames; + trycatch_frames = frame->prev; + free(frame); +} + +void _Noreturn +trycatch_throw(int ex) +{ + if (trycatch_frames == NULL) { + fputs("Exception with no handler!\n", stderr); + abort(); + } + + longjmp(*trycatch_frames->jmpbuf, ex); +} diff --git a/trycatch.h b/trycatch.h new file mode 100644 index 0000000..1ce82ae --- /dev/null +++ b/trycatch.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TRYCATCH_H__ +#define __TRYCATCH_H__ + +#include +#include + +#define TRYCATCH_CONCAT2(a, b) a ## b +#define TRYCATCH_CONCAT(a, b) TRYCATCH_CONCAT2(a, b) +#ifndef TRYCATCH_NORETURN +# define TRYCATCH_NORETURN +#endif +#define try \ + struct trycatch_frame *TRYCATCH_CONCAT(trycatch_frame, __LINE__); \ + jmp_buf TRYCATCH_CONCAT(trycatch_jmpbuf, __LINE__); \ + TRYCATCH_CONCAT(trycatch_frame, __LINE__) = trycatch_frame_push(); \ + trycatch_ex = setjmp(TRYCATCH_CONCAT(trycatch_jmpbuf, __LINE__)); \ + if (trycatch_ex == 0) \ + TRYCATCH_CONCAT(trycatch_frame, __LINE__)->jmpbuf = \ + &TRYCATCH_CONCAT(trycatch_jmpbuf, __LINE__); \ + if (trycatch_ex == 0) +#define catch(ex) \ + trycatch_frame_pop(); \ + for (int ex = trycatch_ex; trycatch_ex != 0; trycatch_ex = 0) +#define throw(ex) trycatch_throw(ex) +#define rethrow trycatch_throw(trycatch_ex) + +struct trycatch_frame { + jmp_buf *jmpbuf; + struct trycatch_frame *prev; +}; + +static int trycatch_ex; + +struct trycatch_frame *trycatch_frame_push(void); +void trycatch_frame_pop(void); +void TRYCATCH_NORETURN trycatch_throw(int ex); + +#endif