home *** CD-ROM | disk | FTP | other *** search
-
- /* low-level.c.x
- *
- * Dreamscape - C++ class library for RISC OS
- * Copyright (c) 1996 Mark Seaborn <mseaborn@argonet.co.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- * See the Dreamscape documentation for more information.
- */
-
- #include <stdlib.h>
- #include <signal.h>
- #include "OS:os.h"
- #include "OS:wimp.h"
- #include "OS:messagetrans.h"
- #include "bool.h"
- #include "kernel.h"
-
- #include "x.h"
-
-
- typedef struct handler_node handler_node;
- struct handler_node {
- jmp_buf jump;
- RISCOSError *error;
- handler_node *next;
- };
-
- static handler_node *handlers = 0;
- static RISCOSError error_buffer, *last_error = 0;
- static bool initialised = 0;
- static char *error_memory = 0, *error_internal = 0;
-
- static void error_handler(int sig);
- static void illegal_address_handler(int sig);
- static void illegal_instruction_handler(int sig);
-
- static void default_error_reporter(const char *error);
- void (*x_error_reporter)(const char *error) = default_error_reporter;
-
- const RISCOSError *x_buffer_error_(const RISCOSError *error)
- {
- error_buffer = *error;
- return &error_buffer;
- }
-
- const RISCOSError *x_buffer_error_msg_(const char *message)
- {
- error_buffer.errnum = 0;
- strcpy(error_buffer.errmess, message);
- return &error_buffer;
- }
-
- const RISCOSError *x_catch_(void)
- {
- RISCOSError *error;
- handler_node *old;
-
- error = handlers->error;
- old = handlers;
- handlers = handlers->next;
- free(old);
- last_error = error;
- return error;
- }
-
- int *x_try_(void)
- {
- handler_node *n = malloc(sizeof(handler_node));
- n->error = 0;
- n->next = handlers;
- handlers = n;
-
- if(!initialised) {
- signal(SIGOSERROR, error_handler);
- signal(SIGSEGV, illegal_address_handler);
- signal(SIGILL, illegal_instruction_handler);
- initialised = 1;
- }
- return n->jump;
- }
-
- static void error_handler(int sig)
- {
- RISCOSError *e = (RISCOSError *) _kernel_last_oserror();
-
- if(handlers) {
- signal(SIGOSERROR, error_handler);
- handlers->error = e;
- longjmp(handlers->jump, 1);
- }
- else {
- x_report_error(e->errmess);
- exit(1);
- }
- }
-
- static void illegal_address_handler(int sig)
- {
- error_buffer.errnum = 0;
- strcpy(error_buffer.errmess, x_msg_internal("Illegal address eg. "
- "wildly outside array bounds"));
-
- if(handlers) {
- signal(SIGSEGV, illegal_address_handler);
- handlers->error = &error_buffer;
- longjmp(handlers->jump, 1);
- }
- else {
- x_report_error(error_buffer.errmess);
- exit(1);
- }
- }
-
- static void illegal_instruction_handler(int sig)
- {
- error_buffer.errnum = 0;
- strcpy(error_buffer.errmess, x_msg_internal("Illegal instruction − "
- "call to non-function/code overwritten"));
-
- if(handlers) {
- signal(SIGILL, illegal_instruction_handler);
- handlers->error = &error_buffer;
- longjmp(handlers->jump, 1);
- }
- else {
- x_report_error(error_buffer.errmess);
- exit(1);
- }
- }
-
- const char *x_msg_memory_(void)
- {
- char *temp;
- int size;
- if(error_memory) return error_memory;
-
- temp = messagetrans_lookup(0, "NoMem", 0, 0, 0, 0, 0, 0, &size);
- error_memory = malloc(size+1);
- if(!error_memory) return "Not enough memory";
- strcpy(error_memory, temp);
- return error_memory;
- }
-
- const char *x_msg_internal_(const char *message)
- {
- if(error_internal) free(error_internal);
- error_internal = malloc(strlen(message) + 20);
- strcpy(error_internal, "Internal error (");
- strcat(error_internal, message);
- strcat(error_internal, ")");
- return error_internal;
- }
-
- const RISCOSError *x_last_error(void)
- {
- return last_error;
- }
-
- static void default_error_reporter(const char *error)
- {
- os_error block;
- block.errnum = 0;
- strncpy(block.errmess, error, 250)[250] = 0;
-
- wimp_report_error(&block, wimp_ERROR_BOX_OK_ICON |
- wimp_ERROR_BOX_SHORT_TITLE, "Error");
- }
-