| /* 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)); | 
 | } |