home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / dreamscape / source / Dreamscape / Sources / low-level / c / x < prev   
Encoding:
Text File  |  1996-09-27  |  3.8 KB  |  172 lines

  1.  
  2. /* low-level.c.x
  3.  *
  4.  * Dreamscape - C++ class library for RISC OS
  5.  * Copyright (c) 1996 Mark Seaborn <mseaborn@argonet.co.uk>
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  * See the Dreamscape documentation for more information.
  12.  */
  13.  
  14. #include <stdlib.h>
  15. #include <signal.h>
  16. #include "OS:os.h"
  17. #include "OS:wimp.h"
  18. #include "OS:messagetrans.h"
  19. #include "bool.h"
  20. #include "kernel.h"
  21.  
  22. #include "x.h"
  23.  
  24.  
  25. typedef struct handler_node handler_node;
  26. struct handler_node {
  27.   jmp_buf jump;
  28.   RISCOSError *error;
  29.   handler_node *next;
  30. };
  31.  
  32. static handler_node *handlers = 0;
  33. static RISCOSError error_buffer, *last_error = 0;
  34. static bool initialised = 0;
  35. static char *error_memory = 0, *error_internal = 0;
  36.  
  37. static void error_handler(int sig);
  38. static void illegal_address_handler(int sig);
  39. static void illegal_instruction_handler(int sig);
  40.  
  41. static void default_error_reporter(const char *error);
  42. void (*x_error_reporter)(const char *error) = default_error_reporter;
  43.  
  44. const RISCOSError *x_buffer_error_(const RISCOSError *error)
  45. {
  46.   error_buffer = *error;
  47.   return &error_buffer;
  48. }
  49.  
  50. const RISCOSError *x_buffer_error_msg_(const char *message)
  51. {
  52.   error_buffer.errnum = 0;
  53.   strcpy(error_buffer.errmess, message);
  54.   return &error_buffer;
  55. }
  56.  
  57. const RISCOSError *x_catch_(void)
  58. {
  59.   RISCOSError *error;
  60.   handler_node *old;
  61.  
  62.   error = handlers->error;
  63.   old = handlers;
  64.   handlers = handlers->next;
  65.   free(old);
  66.   last_error = error;
  67.   return error;
  68. }
  69.  
  70. int *x_try_(void)
  71. {
  72.   handler_node *n = malloc(sizeof(handler_node));
  73.   n->error = 0;
  74.   n->next = handlers;
  75.   handlers = n;
  76.  
  77.   if(!initialised) {
  78.     signal(SIGOSERROR, error_handler);
  79.     signal(SIGSEGV, illegal_address_handler);
  80.     signal(SIGILL, illegal_instruction_handler);
  81.     initialised = 1;
  82.   }
  83.   return n->jump;
  84. }
  85.  
  86. static void error_handler(int sig)
  87. {
  88.   RISCOSError *e = (RISCOSError *) _kernel_last_oserror();
  89.  
  90.   if(handlers) {
  91.     signal(SIGOSERROR, error_handler);
  92.     handlers->error = e;
  93.     longjmp(handlers->jump, 1);
  94.   }
  95.   else {
  96.     x_report_error(e->errmess);
  97.     exit(1);
  98.   }
  99. }
  100.  
  101. static void illegal_address_handler(int sig)
  102. {
  103.   error_buffer.errnum = 0;
  104.   strcpy(error_buffer.errmess, x_msg_internal("Illegal address eg. "
  105.     "wildly outside array bounds"));
  106.  
  107.   if(handlers) {
  108.     signal(SIGSEGV, illegal_address_handler);
  109.     handlers->error = &error_buffer;
  110.     longjmp(handlers->jump, 1);
  111.   }
  112.   else {
  113.     x_report_error(error_buffer.errmess);
  114.     exit(1);
  115.   }
  116. }
  117.  
  118. static void illegal_instruction_handler(int sig)
  119. {
  120.   error_buffer.errnum = 0;
  121.   strcpy(error_buffer.errmess, x_msg_internal("Illegal instruction − "
  122.     "call to non-function/code overwritten"));
  123.  
  124.   if(handlers) {
  125.     signal(SIGILL, illegal_instruction_handler);
  126.     handlers->error = &error_buffer;
  127.     longjmp(handlers->jump, 1);
  128.   }
  129.   else {
  130.     x_report_error(error_buffer.errmess);
  131.     exit(1);
  132.   }
  133. }
  134.  
  135. const char *x_msg_memory_(void)
  136. {
  137.   char *temp;
  138.   int size;
  139.   if(error_memory) return error_memory;
  140.  
  141.   temp = messagetrans_lookup(0, "NoMem", 0, 0, 0, 0, 0, 0, &size);
  142.   error_memory = malloc(size+1);
  143.   if(!error_memory) return "Not enough memory";
  144.   strcpy(error_memory, temp);
  145.   return error_memory;
  146. }
  147.  
  148. const char *x_msg_internal_(const char *message)
  149. {
  150.   if(error_internal) free(error_internal);
  151.   error_internal = malloc(strlen(message) + 20);
  152.   strcpy(error_internal, "Internal error (");
  153.   strcat(error_internal, message);
  154.   strcat(error_internal, ")");
  155.   return error_internal;
  156. }
  157.  
  158. const RISCOSError *x_last_error(void)
  159. {
  160.   return last_error;
  161. }
  162.  
  163. static void default_error_reporter(const char *error)
  164. {
  165.   os_error block;
  166.   block.errnum = 0;
  167.   strncpy(block.errmess, error, 250)[250] = 0;
  168.  
  169.   wimp_report_error(&block, wimp_ERROR_BOX_OK_ICON |
  170.     wimp_ERROR_BOX_SHORT_TITLE, "Error");
  171. }
  172.