| /* SysExceptions.c configure the signals to create m2 exceptions. |
| |
| Copyright (C) 2009-2022 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
| |
| This file is part of GNU Modula-2. |
| |
| GNU Modula-2 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, or (at your option) |
| any later version. |
| |
| GNU Modula-2 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. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include <config.h> |
| #include "m2rts.h" |
| |
| #define EXPORT(FUNC) m2pim ## _SysExceptions_ ## FUNC |
| #define M2EXPORT(FUNC) m2pim ## _M2_SysExceptions_ ## FUNC |
| #define M2LIBNAME "m2pim" |
| |
| #if defined(HAVE_SIGNAL_H) |
| #include <signal.h> |
| #endif |
| |
| #if defined(HAVE_ERRNO_H) |
| #include <errno.h> |
| #endif |
| |
| #if defined(HAVE_SYS_ERRNO_H) |
| #include <sys/errno.h> |
| #endif |
| |
| #if defined(HAVE_STDIO_H) |
| #include <stdio.h> |
| #endif |
| |
| #include "m2rts.h" |
| |
| #if 0 |
| /* Signals. */ |
| #define SIGHUP 1 /* Hangup (POSIX). */ |
| #define SIGINT 2 /* Interrupt (ANSI). */ |
| #define SIGQUIT 3 /* Quit (POSIX). */ |
| #define SIGILL 4 /* Illegal instruction (ANSI). */ |
| #define SIGTRAP 5 /* Trace trap (POSIX). */ |
| #define SIGABRT 6 /* Abort (ANSI). */ |
| #define SIGIOT 6 /* IOT trap (4.2 BSD). */ |
| #define SIGBUS 7 /* BUS error (4.2 BSD). */ |
| #define SIGFPE 8 /* Floating-point exception (ANSI). */ |
| #define SIGKILL 9 /* Kill, unblockable (POSIX). */ |
| #define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ |
| #define SIGSEGV 11 /* Segmentation violation (ANSI). */ |
| #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ |
| #define SIGPIPE 13 /* Broken pipe (POSIX). */ |
| #define SIGALRM 14 /* Alarm clock (POSIX). */ |
| #define SIGTERM 15 /* Termination (ANSI). */ |
| #define SIGSTKFLT 16 /* Stack fault. */ |
| #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ |
| #define SIGCHLD 17 /* Child status has changed (POSIX). */ |
| #define SIGCONT 18 /* Continue (POSIX). */ |
| #define SIGSTOP 19 /* Stop, unblockable (POSIX). */ |
| #define SIGTSTP 20 /* Keyboard stop (POSIX). */ |
| #define SIGTTIN 21 /* Background read from tty (POSIX). */ |
| #define SIGTTOU 22 /* Background write to tty (POSIX). */ |
| #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ |
| #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ |
| #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ |
| #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ |
| #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ |
| #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ |
| #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ |
| #define SIGIO 29 /* I/O now possible (4.2 BSD). */ |
| #define SIGPWR 30 /* Power failure restart (System V). */ |
| #define SIGSYS 31 /* Bad system call. */ |
| #define SIGUNUSED 31 |
| |
| /* The list of Modula-2 exceptions is shown below */ |
| |
| (indexException, rangeException, caseSelectException, invalidLocation, |
| functionException, wholeValueException, wholeDivException, realValueException, |
| realDivException, complexValueException, complexDivException, protException, |
| sysException, coException, exException |
| ); |
| |
| #endif |
| |
| /* Note: wholeDivException and realDivException are caught by SIGFPE |
| and depatched to the appropriate Modula-2 runtime routine upon |
| testing FPE_INTDIV or FPE_FLTDIV. realValueException is also |
| caught by SIGFPE and dispatched by testing FFE_FLTOVF or FPE_FLTUND |
| or FPE_FLTRES or FPE_FLTINV. indexException is caught by SIGFPE |
| and dispatched by FPE_FLTSUB. */ |
| |
| #if defined(HAVE_SIGNAL_H) |
| static struct sigaction sigbus; |
| static struct sigaction sigfpe; |
| static struct sigaction sigsegv; |
| |
| static void (*indexProc) (void *); |
| static void (*rangeProc) (void *); |
| static void (*assignmentrangeProc) (void *); |
| static void (*caseProc) (void *); |
| static void (*invalidlocProc) (void *); |
| static void (*functionProc) (void *); |
| static void (*wholevalueProc) (void *); |
| static void (*wholedivProc) (void *); |
| static void (*realvalueProc) (void *); |
| static void (*realdivProc) (void *); |
| static void (*complexvalueProc) (void *); |
| static void (*complexdivProc) (void *); |
| static void (*protectionProc) (void *); |
| static void (*systemProc) (void *); |
| static void (*coroutineProc) (void *); |
| static void (*exceptionProc) (void *); |
| |
| static void |
| sigbusDespatcher (int signum, siginfo_t *info, void *ucontext) |
| { |
| switch (signum) |
| { |
| |
| case SIGSEGV: |
| case SIGBUS: |
| if (info) |
| (*invalidlocProc) (info->si_addr); |
| break; |
| default: |
| perror ("not expecting to arrive here with this signal"); |
| } |
| } |
| |
| static void |
| sigfpeDespatcher (int signum, siginfo_t *info, void *ucontext) |
| { |
| switch (signum) |
| { |
| |
| case SIGFPE: |
| if (info) |
| { |
| if (info->si_code | FPE_INTDIV) |
| (*wholedivProc) (info->si_addr); /* Integer divide by zero. */ |
| if (info->si_code | FPE_INTOVF) |
| (*wholevalueProc) (info->si_addr); /* Integer overflow. */ |
| if (info->si_code | FPE_FLTDIV) |
| (*realdivProc) (info->si_addr); /* Floating-point divide by zero. */ |
| if (info->si_code | FPE_FLTOVF) |
| (*realvalueProc) (info->si_addr); /* Floating-point overflow. */ |
| if (info->si_code | FPE_FLTUND) |
| (*realvalueProc) (info->si_addr); /* Floating-point underflow. */ |
| if (info->si_code | FPE_FLTRES) |
| (*realvalueProc) ( |
| info->si_addr); /* Floating-point inexact result. */ |
| if (info->si_code | FPE_FLTINV) |
| (*realvalueProc) ( |
| info->si_addr); /* Floating-point invalid result. */ |
| if (info->si_code | FPE_FLTSUB) |
| (*indexProc) (info->si_addr); /* Subscript out of range. */ |
| } |
| break; |
| default: |
| perror ("not expecting to arrive here with this signal"); |
| } |
| } |
| |
| extern "C" void |
| EXPORT(InitExceptionHandlers) ( |
| void (*indexf) (void *), void (*range) (void *), void (*casef) (void *), |
| void (*invalidloc) (void *), void (*function) (void *), |
| void (*wholevalue) (void *), void (*wholediv) (void *), |
| void (*realvalue) (void *), void (*realdiv) (void *), |
| void (*complexvalue) (void *), void (*complexdiv) (void *), |
| void (*protection) (void *), void (*systemf) (void *), |
| void (*coroutine) (void *), void (*exception) (void *)) |
| { |
| struct sigaction old; |
| |
| indexProc = indexf; |
| rangeProc = range; |
| caseProc = casef; |
| invalidlocProc = invalidloc; |
| functionProc = function; |
| wholevalueProc = wholevalue; |
| wholedivProc = wholediv; |
| realvalueProc = realvalue; |
| realdivProc = realdiv; |
| complexvalueProc = complexvalue; |
| complexdivProc = complexdiv; |
| protectionProc = protection; |
| systemProc = systemf; |
| coroutineProc = coroutine; |
| exceptionProc = exception; |
| |
| sigbus.sa_sigaction = sigbusDespatcher; |
| sigbus.sa_flags = (SA_SIGINFO); |
| sigemptyset (&sigbus.sa_mask); |
| |
| if (sigaction (SIGBUS, &sigbus, &old) != 0) |
| perror ("unable to install the sigbus signal handler"); |
| |
| sigsegv.sa_sigaction = sigbusDespatcher; |
| sigsegv.sa_flags = (SA_SIGINFO); |
| sigemptyset (&sigsegv.sa_mask); |
| |
| if (sigaction (SIGSEGV, &sigsegv, &old) != 0) |
| perror ("unable to install the sigsegv signal handler"); |
| |
| sigfpe.sa_sigaction = sigfpeDespatcher; |
| sigfpe.sa_flags = (SA_SIGINFO); |
| sigemptyset (&sigfpe.sa_mask); |
| |
| if (sigaction (SIGFPE, &sigfpe, &old) != 0) |
| perror ("unable to install the sigfpe signal handler"); |
| } |
| |
| #else |
| extern "C" void |
| EXPORT(InitExceptionHandlers) (void *indexf, void *range, void *casef, |
| void *invalidloc, void *function, |
| void *wholevalue, void *wholediv, |
| void *realvalue, void *realdiv, |
| void *complexvalue, void *complexdiv, |
| void *protection, void *systemf, |
| void *coroutine, void *exception) |
| { |
| } |
| #endif |
| |
| |
| extern "C" void |
| M2EXPORT(init) (int, char **, char **) |
| { |
| } |
| |
| extern "C" void |
| M2EXPORT(fini) (int, char **, char **) |
| { |
| } |
| |
| extern "C" void |
| M2EXPORT(dep) (void) |
| { |
| } |
| |
| extern "C" void __attribute__((__constructor__)) |
| M2EXPORT(ctor) (void) |
| { |
| m2pim_M2RTS_RegisterModule ("SysExceptions", M2LIBNAME, |
| M2EXPORT(init), M2EXPORT(fini), |
| M2EXPORT(dep)); |
| } |