]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | /* GSysExceptions.c low level module interfacing exceptions to the OS. |
2 | ||
a945c346 | 3 | Copyright (C) 2016-2024 Free Software Foundation, Inc. |
1eee94d3 GM |
4 | Contributed by Gaius Mulley <gaius@glam.ac.uk>. |
5 | ||
6 | This file is part of GNU Modula-2. | |
7 | ||
8 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU Modula-2; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | ||
25 | #include "gm2-libs-host.h" | |
26 | ||
27 | #if defined(__cplusplus) | |
28 | #define EXTERN extern "C" | |
29 | #else | |
30 | #define EXTERN | |
31 | #endif | |
32 | ||
33 | #if 0 | |
34 | /* Signals. */ | |
35 | #define SIGHUP 1 /* Hangup (POSIX). */ | |
36 | #define SIGINT 2 /* Interrupt (ANSI). */ | |
37 | #define SIGQUIT 3 /* Quit (POSIX). */ | |
38 | #define SIGILL 4 /* Illegal instruction (ANSI). */ | |
39 | #define SIGTRAP 5 /* Trace trap (POSIX). */ | |
40 | #define SIGABRT 6 /* Abort (ANSI). */ | |
41 | #define SIGIOT 6 /* IOT trap (4.2 BSD). */ | |
42 | #define SIGBUS 7 /* BUS error (4.2 BSD). */ | |
43 | #define SIGFPE 8 /* Floating-point exception (ANSI). */ | |
44 | #define SIGKILL 9 /* Kill, unblockable (POSIX). */ | |
45 | #define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ | |
46 | #define SIGSEGV 11 /* Segmentation violation (ANSI). */ | |
47 | #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ | |
48 | #define SIGPIPE 13 /* Broken pipe (POSIX). */ | |
49 | #define SIGALRM 14 /* Alarm clock (POSIX). */ | |
50 | #define SIGTERM 15 /* Termination (ANSI). */ | |
51 | #define SIGSTKFLT 16 /* Stack fault. */ | |
52 | #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ | |
53 | #define SIGCHLD 17 /* Child status has changed (POSIX). */ | |
54 | #define SIGCONT 18 /* Continue (POSIX). */ | |
55 | #define SIGSTOP 19 /* Stop, unblockable (POSIX). */ | |
56 | #define SIGTSTP 20 /* Keyboard stop (POSIX). */ | |
57 | #define SIGTTIN 21 /* Background read from tty (POSIX). */ | |
58 | #define SIGTTOU 22 /* Background write to tty (POSIX). */ | |
59 | #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ | |
60 | #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ | |
61 | #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ | |
62 | #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ | |
63 | #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ | |
64 | #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ | |
65 | #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ | |
66 | #define SIGIO 29 /* I/O now possible (4.2 BSD). */ | |
67 | #define SIGPWR 30 /* Power failure restart (System V). */ | |
68 | #define SIGSYS 31 /* Bad system call. */ | |
69 | #define SIGUNUSED 31 | |
70 | ||
71 | ||
72 | (indexException, rangeException, caseSelectException, invalidLocation, | |
73 | functionException, wholeValueException, wholeDivException, realValueException, | |
74 | realDivException, complexValueException, complexDivException, protException, | |
75 | sysException, coException, exException | |
76 | ); | |
77 | ||
78 | #endif | |
79 | ||
80 | /* wholeDivException and realDivException are caught by SIGFPE | |
81 | and depatched to the appropriate Modula-2 runtime routine upon | |
82 | testing FPE_INTDIV or FPE_FLTDIV. realValueException is also | |
83 | caught by SIGFPE and dispatched by testing FFE_FLTOVF or | |
84 | FPE_FLTUND or FPE_FLTRES or FPE_FLTINV. indexException is | |
85 | caught by SIGFPE and dispatched by FPE_FLTSUB. */ | |
86 | ||
87 | #if defined(HAVE_SIGNAL_H) | |
88 | static struct sigaction sigbus; | |
89 | static struct sigaction sigfpe_; | |
90 | static struct sigaction sigsegv; | |
91 | ||
92 | static void (*indexProc) (void *); | |
93 | static void (*rangeProc) (void *); | |
94 | static void (*assignmentrangeProc) (void *); | |
95 | static void (*caseProc) (void *); | |
96 | static void (*invalidlocProc) (void *); | |
97 | static void (*functionProc) (void *); | |
98 | static void (*wholevalueProc) (void *); | |
99 | static void (*wholedivProc) (void *); | |
100 | static void (*realvalueProc) (void *); | |
101 | static void (*realdivProc) (void *); | |
102 | static void (*complexvalueProc) (void *); | |
103 | static void (*complexdivProc) (void *); | |
104 | static void (*protectionProc) (void *); | |
105 | static void (*systemProc) (void *); | |
106 | static void (*coroutineProc) (void *); | |
107 | static void (*exceptionProc) (void *); | |
108 | ||
109 | static void | |
110 | sigbusDespatcher (int signum, siginfo_t *info, void *ucontext) | |
111 | { | |
112 | switch (signum) | |
113 | { | |
114 | ||
115 | case SIGSEGV: | |
116 | case SIGBUS: | |
117 | if (info) | |
118 | (*invalidlocProc) (info->si_addr); | |
119 | break; | |
120 | default: | |
121 | perror ("not expecting to arrive here with this signal"); | |
122 | } | |
123 | } | |
124 | ||
125 | static void | |
126 | sigfpeDespatcher (int signum, siginfo_t *info, void *ucontext) | |
127 | { | |
128 | switch (signum) | |
129 | { | |
130 | ||
131 | case SIGFPE: | |
132 | if (info) | |
133 | { | |
134 | if (info->si_code | FPE_INTDIV) | |
135 | (*wholedivProc) (info->si_addr); /* integer divide by zero. */ | |
136 | if (info->si_code | FPE_INTOVF) | |
137 | (*wholevalueProc) (info->si_addr); /* integer overflow. */ | |
138 | if (info->si_code | FPE_FLTDIV) | |
139 | (*realdivProc) ( | |
140 | info->si_addr); /* floating-point divide by zero. */ | |
141 | if (info->si_code | FPE_FLTOVF) | |
142 | (*realvalueProc) (info->si_addr); /* floating-point overflow. */ | |
143 | if (info->si_code | FPE_FLTUND) | |
144 | (*realvalueProc) (info->si_addr); /* floating-point underflow. */ | |
145 | if (info->si_code | FPE_FLTRES) | |
146 | (*realvalueProc) ( | |
147 | info->si_addr); /* floating-point inexact result. */ | |
148 | if (info->si_code | FPE_FLTINV) | |
149 | (*realvalueProc) ( | |
150 | info->si_addr); /* floating-point invalid result. */ | |
151 | if (info->si_code | FPE_FLTSUB) | |
152 | (*indexProc) (info->si_addr); /* subscript out of range. */ | |
153 | } | |
154 | break; | |
155 | default: | |
156 | perror ("not expecting to arrive here with this signal"); | |
157 | } | |
158 | } | |
159 | ||
160 | EXTERN | |
161 | void | |
162 | SysExceptions_InitExceptionHandlers ( | |
163 | void (*indexf) (void *), void (*range) (void *), void (*casef) (void *), | |
164 | void (*invalidloc) (void *), void (*function) (void *), | |
165 | void (*wholevalue) (void *), void (*wholediv) (void *), | |
166 | void (*realvalue) (void *), void (*realdiv) (void *), | |
167 | void (*complexvalue) (void *), void (*complexdiv) (void *), | |
168 | void (*protection) (void *), void (*systemf) (void *), | |
169 | void (*coroutine) (void *), void (*exception) (void *)) | |
170 | { | |
171 | struct sigaction old; | |
172 | ||
173 | indexProc = indexf; | |
174 | rangeProc = range; | |
175 | caseProc = casef; | |
176 | invalidlocProc = invalidloc; | |
177 | functionProc = function; | |
178 | wholevalueProc = wholevalue; | |
179 | wholedivProc = wholediv; | |
180 | realvalueProc = realvalue; | |
181 | realdivProc = realdiv; | |
182 | complexvalueProc = complexvalue; | |
183 | complexdivProc = complexdiv; | |
184 | protectionProc = protection; | |
185 | systemProc = systemf; | |
186 | coroutineProc = coroutine; | |
187 | exceptionProc = exception; | |
188 | ||
189 | sigbus.sa_sigaction = sigbusDespatcher; | |
190 | sigbus.sa_flags = (SA_SIGINFO); | |
191 | sigemptyset (&sigbus.sa_mask); | |
192 | ||
193 | if (sigaction (SIGBUS, &sigbus, &old) != 0) | |
194 | perror ("unable to install the sigbus signal handler"); | |
195 | ||
196 | sigsegv.sa_sigaction = sigbusDespatcher; | |
197 | sigsegv.sa_flags = (SA_SIGINFO); | |
198 | sigemptyset (&sigsegv.sa_mask); | |
199 | ||
200 | if (sigaction (SIGSEGV, &sigsegv, &old) != 0) | |
201 | perror ("unable to install the sigsegv signal handler"); | |
202 | ||
203 | sigfpe_.sa_sigaction = sigfpeDespatcher; | |
204 | sigfpe_.sa_flags = (SA_SIGINFO); | |
205 | sigemptyset (&sigfpe_.sa_mask); | |
206 | ||
207 | if (sigaction (SIGFPE, &sigfpe_, &old) != 0) | |
208 | perror ("unable to install the sigfpe signal handler"); | |
209 | } | |
210 | ||
211 | #else | |
212 | EXTERN | |
213 | void | |
214 | SysExceptions_InitExceptionHandlers (void *indexf, void *range, void *casef, | |
215 | void *invalidloc, void *function, | |
216 | void *wholevalue, void *wholediv, | |
217 | void *realvalue, void *realdiv, | |
218 | void *complexvalue, void *complexdiv, | |
219 | void *protection, void *systemf, | |
220 | void *coroutine, void *exception) | |
221 | { | |
222 | } | |
223 | #endif | |
224 | ||
225 | /* GNU Modula-2 linking fodder. */ | |
226 | ||
227 | EXTERN | |
228 | void | |
9fadd8de | 229 | _M2_SysExceptions_init (int argc, char *argv[], char *envp[]) |
1eee94d3 GM |
230 | { |
231 | } | |
232 | ||
233 | EXTERN | |
234 | void | |
9fadd8de | 235 | _M2_SysExceptions_fini (int argc, char *argv[], char *envp[]) |
1eee94d3 GM |
236 | { |
237 | } |