Exceptions.C 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. // $XConsortium: Exceptions.cc /main/3 1996/06/11 16:51:03 cde-hal $
  24. #ifndef NATIVE_EXCEPTIONS
  25. #include "Exceptions.hh"
  26. //#include <new.h>
  27. #include <memory.h>
  28. #include <string.h>
  29. #ifdef C_API
  30. char* Exceptions::f_msg_internal_error = 0;
  31. char* Exceptions::f_msg_application_error = 0;
  32. char* Exceptions::f_msg_throw_message = 0;
  33. char* Exceptions::f_msg_not_initialized = 0;
  34. char* Exceptions::f_msg_initialized_twice = 0;
  35. char* Exceptions::f_msg_not_caught = 0;
  36. char* Exceptions::f_msg_no_current_exception = 0;
  37. char* Exceptions::f_msg_throw_from_terminate = 0;
  38. char* Exceptions::f_msg_throw_from_error_handler = 0;
  39. char* Exceptions::f_msg_throw_from_destructor = 0;
  40. char* Exceptions::f_msg_throw_ptr_to_stack = 0;
  41. char* Exceptions::f_msg_out_of_exception_memory = 0;
  42. char* Exceptions::f_msg_out_of_obj_stack_memory = 0;
  43. char* Exceptions::f_msg_memory_already_freed = 0;
  44. #else
  45. char *Exceptions::f_msg_internal_error =
  46. (char*)"Internal exceptions error:";
  47. char *Exceptions::f_msg_application_error =
  48. (char*)"Application exceptions error:";
  49. char *Exceptions::f_msg_throw_message =
  50. (char*)"Application threw exception:";
  51. char *Exceptions::f_msg_not_initialized =
  52. (char*)"Exceptions library not initialized with INIT_EXCEPTIONS().";
  53. char *Exceptions::f_msg_initialized_twice =
  54. (char*)"Attept to call INIT_EXCEPTIONS() more than once.";
  55. char *Exceptions::f_msg_not_caught =
  56. (char*)"Exception not caught.";
  57. char *Exceptions::f_msg_no_current_exception =
  58. (char*)"There is no current exception (for catch or rethrow).";
  59. char *Exceptions::f_msg_throw_from_terminate =
  60. (char*)"Exceptions may not be thrown from terminate.";
  61. char *Exceptions::f_msg_throw_from_error_handler =
  62. (char*)"Exceptions may not be thrown from error handler.";
  63. char *Exceptions::f_msg_throw_from_destructor =
  64. (char*)"Exited destructor with throw while handling an exception.";
  65. char *Exceptions::f_msg_throw_ptr_to_stack =
  66. (char*)"Threw a pointer to an automatic (stack-based) exceptions object.";
  67. char *Exceptions::f_msg_out_of_exception_memory =
  68. (char*)"Not enough memory to allocate an exception object.";
  69. char *Exceptions::f_msg_out_of_obj_stack_memory =
  70. (char*)"Not enough memory to allocate object stack.";
  71. char *Exceptions::f_msg_memory_already_freed =
  72. (char*)"Tried to alloc or realloc pool memory that was previously freed.";
  73. #endif
  74. // /////////////////////////////////////////////////////////////////
  75. // initialize - initialize the exceptions library
  76. // /////////////////////////////////////////////////////////////////
  77. void
  78. Exceptions::initialize (void *ptr)
  79. {
  80. PRINTF (("Initializing exceptions library\n"));
  81. if (Destructable::g_stack_start != NULL)
  82. {
  83. error (f_msg_initialized_twice, APPLICATION_ERROR);
  84. terminate();
  85. }
  86. else
  87. {
  88. // These two values MUST be initialized before the static
  89. // Jump_Environment below, or the its Destructable base class
  90. // constructor will fail because it won't think the library
  91. // is initialized or it may think the Jump Environment is on
  92. // the stack because f_stack_start is 0.
  93. Destructable::g_stack_start = ptr;
  94. // The following is the global jump environment. According to ARM
  95. // (6.7) this isn't initialized until the first call to this function,
  96. // NOT at a global level before main() is called. This is important
  97. // because Jump_Environment is subclassed of Destructable, whose
  98. // constructor expects g_stack_start to be non-zero.
  99. static Jump_Environment __jump_env;
  100. if (setjmp (__jump_env.f_env) != 0)
  101. {
  102. // Re-set base environment to allow for the creation of
  103. // Destructable objects in error handler and terminate
  104. // terminate function.
  105. Jump_Environment::g_jump_env_stack = &__jump_env;
  106. error (f_msg_not_caught, APPLICATION_ERROR);
  107. terminate();
  108. }
  109. }
  110. }
  111. // Static variable declarations
  112. Exceptions::error_handler_t Exceptions::g_error_handler;
  113. // Error message declarations
  114. // The error messages are stored here because many appear in the
  115. // header files and we don't want to duplicate them in every app
  116. // that uses the header files.
  117. // /////////////////////////////////////////////////////////////////
  118. // set_error_handler
  119. // /////////////////////////////////////////////////////////////////
  120. Exceptions::error_handler_t
  121. Exceptions::set_error_handler (error_handler_t error_handler)
  122. {
  123. error_handler_t previous = g_error_handler;
  124. g_error_handler = error_handler;
  125. return (previous);
  126. }
  127. // /////////////////////////////////////////////////////////////////
  128. // error - print a useful error message
  129. // /////////////////////////////////////////////////////////////////
  130. void
  131. Exceptions::error (const char *message, error_type_t error_type)
  132. {
  133. const unsigned int bufferlen = 100;
  134. char buffer[3][bufferlen];
  135. static char *lines[3] = { buffer[0], buffer[1], buffer[2] };
  136. int len, count = 0;
  137. if (error_type == INTERNAL_ERROR) {
  138. len = MIN(strlen(f_msg_internal_error), bufferlen - 1);
  139. *((char *) memcpy(buffer[count++], f_msg_internal_error, len) + len) = '\0';
  140. }
  141. else if (error_type == APPLICATION_ERROR) {
  142. len = MIN(strlen(f_msg_application_error), bufferlen - 1);
  143. *((char *) memcpy(buffer[count++], f_msg_application_error,len)+len) = '\0';
  144. }
  145. else {
  146. len = MIN(strlen(f_msg_throw_message), bufferlen - 1);
  147. *((char *) memcpy(buffer[count++], f_msg_throw_message, len) + len) = '\0';
  148. }
  149. // Don't use fprintf because it may try to allocate memory.
  150. if (Exception::g_current_exception != NULL)
  151. {
  152. snprintf (buffer[count++], bufferlen,
  153. " In exception thrown in file \"%s\", line %d,",
  154. Exception::g_current_exception->f_file,
  155. Exception::g_current_exception->f_line);
  156. }
  157. if (message != NULL)
  158. snprintf (buffer[count++], bufferlen, " %s", message);
  159. // Call user print function if set, otherwise just dump lines.
  160. if (g_error_handler != NULL)
  161. {
  162. mtry
  163. {
  164. // Reset global variable to NULL before calling to prevent
  165. // the possibility of recursive calls.
  166. Exceptions::error_handler_t current = set_error_handler (NULL);
  167. (*current) ((const char**)lines, count);
  168. set_error_handler (current);
  169. }
  170. mcatch_any()
  171. {
  172. // Error handler will be NULL at this point.
  173. Exceptions::error (Exceptions::f_msg_throw_from_error_handler,
  174. Exceptions::APPLICATION_ERROR);
  175. terminate();
  176. }
  177. end_try;
  178. }
  179. else
  180. {
  181. for (int i = 0; i < count; i++)
  182. {
  183. fputs (buffer[i], stderr);
  184. fputc ('\n', stderr);
  185. }
  186. }
  187. }
  188. // /////////////////////////////////////////////////////////////////
  189. // check_initialized - exit with error if not initialized
  190. // /////////////////////////////////////////////////////////////////
  191. void
  192. Exceptions::check_initialized()
  193. {
  194. void terminate();
  195. if (Destructable::g_stack_start == NULL)
  196. {
  197. // Can't call user defined error handler unless we're initialized.
  198. // Also can't do lazy initialization because we need the stack
  199. // pointer from the start of main, not here. From here is good
  200. // enough for terminating, however.
  201. INIT_EXCEPTIONS();
  202. error (f_msg_not_initialized, APPLICATION_ERROR);
  203. terminate();
  204. }
  205. }
  206. #endif /* NATIVE_EXCEPTIONS */