blob: d93e79e3d558ac84e4f1cc0ef63ebffa883ca824 [file] [log] [blame]
/* 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));
}