chiark / gitweb /
9cc03060164d02b02865e40e4fe2872c2e94a560
[mLib] / exc.c
1 /* -*-c-*-
2  *
3  * Structured exception handling in C
4  *
5  * (c) 1998 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "exc.h"
33
34 /*----- Global variables --------------------------------------------------*/
35
36 __exc_hnd *__exc_list = 0;
37
38 /*----- Functions ---------------------------------------------------------*/
39
40 /* --- @duff@ --- *
41  *
42  * Arguments:   @exc_extype type@ = type of duff exception
43  *              @exc_exval val@ = extra data supplied
44  *
45  * Returns:     Doesn't
46  *
47  * Use:         Default handler when everything goes wrong.
48  */
49
50 static void duff(exc_extype type, exc_exval val)
51 {
52   fprintf(stderr, "fatal error: uncaught exception (type = %lx)\n", type);
53   abort();
54 }
55
56 /* --- @duffproc@ --- *
57  *
58  * Current handler when there are no more exceptions left.
59  */
60
61 static exc__uncaught duffproc = duff;
62
63 /* --- @exc_uncaught@ --- *
64  *
65  * Arguments:   @void (*proc)(exc_extype type, exc_exval val) = new handler
66  *
67  * Returns:     Pointer to the old handler value.
68  *
69  * Use:         Sets the handler for uncaught exceptions.
70  */
71
72 exc__uncaught exc_uncaught(exc__uncaught proc)
73 {
74   exc__uncaught p = duffproc;
75   if (proc)
76     duffproc = proc;
77   return (p);
78 }
79
80 /* --- @__exc_throw@ --- *
81  *
82  * Arguments:   @exc_extype type@ = type of exception to throw
83  *
84  * Returns:     Doesn't
85  *
86  * Use:         NOT FOR USER CONSUMPTION.  Reads an appropriate exception
87  *              value and throws an exception.
88  */
89
90 void __exc_throw(exc_extype type, ...)
91 {
92   va_list ap;
93   exc_exval v;
94
95   va_start(ap, type);
96   switch (type & 0xC0) {
97     case EXC_NOVAL:
98       v.i = 0;
99       break;
100     case EXC_INTVAL:
101       v.i = va_arg(ap, int);
102       break;
103     case EXC_PTRVAL:
104       v.p = va_arg(ap, void *);
105       break;
106     case EXC_STRVAL:
107       v.s = va_arg(ap, char *);
108       break;
109   }
110   va_end(ap);
111   __exc_rethrow(type, v);
112 }
113
114 /* --- @__exc_rethrow@ --- *
115  *
116  * Arguments:   @exc_extype type@ = type of exception to throw
117  *              @exc_exval val@ = value of exception to throw
118  *
119  * Returns:     Doesn't
120  *
121  * Use:         NOT FOR USER CONSUMPTION.  Does the donkey-work of raising
122  *              an exception.
123  */
124
125 void __exc_rethrow(exc_extype type, exc_exval val)
126 {
127   __exc_hnd *p = __exc_list;
128   if (!p)
129     duffproc(type, val);
130   p->type = type;
131   p->val = val;
132   __exc_list = p->next;
133   longjmp(p->buf, type);
134 }
135
136 /*----- That's all, folks -------------------------------------------------*/