compiler/bootstrap/SYSTEM.c
2024-04-13 04:14:18 +04:00

227 lines
6.5 KiB
C

/*
* The body prefix file of the voc(jet backend) runtime system, Version 1.0
*
* Copyright (c) Software Templ, 1994, 1995
*
* Module SYSTEM is subject to change any time without prior notification.
* Software Templ disclaims all warranties with regard to module SYSTEM,
* in particular shall Software Templ not be liable for any damage resulting
* from inappropriate use or modification of module SYSTEM.
*
* Version 1.1 jt, 24.11.95 fixes for correct pointer arithmetic on Cray computers
* jt 31.1.2007 ANSI prototypes for malloc and exit in order to avoid cc warnings
*
*/
#include "SYSTEM.h"
#include "stdarg.h"
#include <signal.h>
// Procedure verions of SYSTEM.H versions used when a multiply accessed
// parameter has side effects.
INT64 SYSTEM_DIV(INT64 x, INT64 y)
{
if (x == 0) return 0;
if (x >= 0)
if (y >= 0) {return x/y;}
else {return -((x-y-1)/(-y));}
else
if (y >= 0) {return -((y-x-1)/y);}
else {return (-x)/(-y);}
}
INT64 SYSTEM_MOD(INT64 x, INT64 y)
{
if (x == 0) return 0;
if (x >= 0)
if (y >= 0) {return x % y;}
else {return (y+1) + ((x-1) % (-y));}
else
if (y >= 0) {return (y-1) - ((-x-1) % y);}
else {return -((-x) % (-y));}
}
INT64 SYSTEM_ENTIER(double x)
{
INT64 y;
if (x >= 0)
return (INT64)x;
else {
y = (INT64)x;
if (y <= x) return y; else return y - 1;
}
}
void SYSTEM_INHERIT(ADDRESS *t, ADDRESS *t0)
{
t -= __TPROC0OFF;
t0 -= __TPROC0OFF;
while (*t0 != __EOM) {*t = *t0; t--; t0--;}
}
void SYSTEM_ENUMP(void *adr, ADDRESS n, void (*P)())
{
while (n > 0) {
P((ADDRESS)(*((void**)(adr))));
adr = ((void**)adr) + 1;
n--;
}
}
void SYSTEM_ENUMR(void *adr, ADDRESS *typ, ADDRESS size, ADDRESS n, void (*P)())
{
ADDRESS *t, off;
typ++;
while (n > 0) {
t = typ;
off = *t;
while (off >= 0) {P(*(ADDRESS*)((char*)adr+off)); t++; off = *t;}
adr = ((char*)adr) + size;
n--;
}
}
extern void Heap_Lock();
extern void Heap_Unlock();
SYSTEM_PTR SYSTEM_NEWARR(ADDRESS *typ, ADDRESS elemsz, int elemalgn, int nofdim, int nofdyn, ...)
{
ADDRESS nofelems, size, dataoff, n, nptr, *x, *p, nofptrs, i, *ptab, off;
va_list ap;
va_start(ap, nofdyn);
nofelems = 1;
while (nofdim > 0) {
nofelems = nofelems * va_arg(ap, ADDRESS); nofdim--;
if (nofelems <= 0) __HALT(-20);
}
va_end(ap);
dataoff = nofdyn * sizeof(ADDRESS);
if (elemalgn > sizeof(ADDRESS)) {
n = dataoff % elemalgn;
if (n != 0) dataoff += elemalgn - n;
}
size = dataoff + nofelems * elemsz;
Heap_Lock();
if (typ == NIL) {
/* element typ does not contain pointers */
x = Heap_NEWBLK(size);
}
else if (typ == (ADDRESS*)POINTER__typ) {
/* element type is a pointer */
x = Heap_NEWBLK(size + nofelems * sizeof(ADDRESS));
p = (ADDRESS*)(ADDRESS)x[-1];
p[-nofelems] = *p; /* build new type desc in situ: 1. copy block size; 2. setup ptr tab; 3. set sentinel; 4. patch tag */
p -= nofelems - 1; n = 1; /* n =1 for skipping the size field */
while (n <= nofelems) {*p = n*sizeof(ADDRESS); p++; n++;}
*p = - (nofelems + 1) * sizeof(ADDRESS); /* sentinel */
x[-1] -= nofelems * sizeof(ADDRESS);
}
else {
/* element type is a record that contains pointers */
ptab = typ + 1; nofptrs = 0;
while (ptab[nofptrs] >= 0) {nofptrs++;} /* number of pointers per element */
nptr = nofelems * nofptrs; /* total number of pointers */
x = Heap_NEWBLK(size + nptr * sizeof(ADDRESS));
p = (ADDRESS*)(ADDRESS)x[- 1];
p[-nptr] = *p; /* build new type desc in situ; 1. copy block size; 2. setup ptr tab; 3. set sentinel; 4. patch tag */
p -= nptr - 1; n = 0; off = dataoff;
while (n < nofelems) {i = 0;
while (i < nofptrs) {*p = off + ptab[i]; p++; i++;}
off += elemsz; n++;
}
*p = - (nptr + 1) * sizeof(ADDRESS); /* sentinel */
x[-1] -= nptr * sizeof(ADDRESS);
}
if (nofdyn != 0) {
/* setup len vector for index checks */
va_start(ap, nofdyn);
p = x;
while (nofdyn > 0) {*p = va_arg(ap, ADDRESS); p++, nofdyn--;}
va_end(ap);
}
Heap_Unlock();
return x;
}
typedef void (*SystemSignalHandler)(INT32); // = Platform_SignalHandler
#ifndef _WIN32
// Unix signal handling
SystemSignalHandler handler[10] = {0}; // Adjust the array size to include signal 11
void segfaultHandler(int signal) {
__HALT(-10);
}
// Revised signal handler to accommodate additional signals like SIGSEGV
void signalHandler(int s) {
if ((s >= 2 && s <= 4) || s == 11) { // Include SIGSEGV (usually signal 11)
if (handler[s-2]) {
handler[s-2](s);
}
}
// Ignore other signals
}
void SystemSetHandler(int s, ADDRESS h) {
if ((s >= 2 && s <= 4) || s == 11) {
int needtosetsystemhandler = handler[s-2] == 0;
handler[s-2] = (SystemSignalHandler)h;
if (needtosetsystemhandler) {
signal(s, signalHandler);
}
}
}
void setupAutomaticSegfaultHandler() {
SystemSetHandler(11, (ADDRESS)segfaultHandler); // Register handler for SIGSEGV
}
#else
// Windows system remains as is since Windows does not use SIGSEGV in the same way
#include "WindowsWrapper.h"
SystemSignalHandler SystemInterruptHandler = 0;
SystemSignalHandler SystemQuitHandler = 0;
BOOL ConsoleCtrlHandlerSet = FALSE;
BOOL WINAPI SystemConsoleCtrlHandler(DWORD ctrlType) {
if ((ctrlType == CTRL_C_EVENT) || (ctrlType == CTRL_BREAK_EVENT)) {
if (SystemInterruptHandler) {
SystemInterruptHandler(2); // SIGINT
return TRUE;
}
} else {
if (SystemQuitHandler) {
SystemQuitHandler(3); // SIGQUIT
return TRUE;
}
}
return FALSE;
}
void EnsureConsoleCtrlHandler() {
if (!ConsoleCtrlHandlerSet) {
SetConsoleCtrlHandler(SystemConsoleCtrlHandler, TRUE);
ConsoleCtrlHandlerSet = TRUE;
}
}
void SystemSetInterruptHandler(ADDRESS h) {
EnsureConsoleCtrlHandler();
SystemInterruptHandler = (SystemSignalHandler)h;
}
void SystemSetQuitHandler(ADDRESS h) {
EnsureConsoleCtrlHandler();
SystemQuitHandler = (SystemSignalHandler)h;
}
#endif