#pragma implementation "exception"
#include "typeinfo"
#include "exception"
#include <stddef.h>
#include "gansidecl.h"
#include "eh-common.h"
#ifndef MACOSX
extern std::terminate_handler __terminate_func __attribute__((__noreturn__));
using std::terminate;
void
std::terminate ()
{
__terminate_func ();
}
void
__default_unexpected ()
{
terminate ();
}
static std::unexpected_handler __unexpected_func __attribute__((__noreturn__))
= __default_unexpected;
std::terminate_handler
std::set_terminate (std::terminate_handler func)
{
std::terminate_handler old = __terminate_func;
__terminate_func = func;
return old;
}
std::unexpected_handler
std::set_unexpected (std::unexpected_handler func)
{
std::unexpected_handler old = __unexpected_func;
__unexpected_func = func;
return old;
}
void
std::unexpected ()
{
__unexpected_func ();
}
#else
#include "apple/keymgr.h"
using std::terminate;
void
std::terminate ()
{
void (*__terminate_func)() =
(void (*)()) _keymgr_get_per_thread_data (KEYMGR_TERMINATE_HANDLER_KEY);
if (__terminate_func == NULL)
abort ();
else
(*__terminate_func) ();
}
std::terminate_handler
std::set_terminate (std::terminate_handler func)
{
std::terminate_handler old =
(std::terminate_handler) _keymgr_get_per_thread_data (KEYMGR_TERMINATE_HANDLER_KEY);
_keymgr_set_per_thread_data(KEYMGR_TERMINATE_HANDLER_KEY,func) ;
return old;
}
std::unexpected_handler
std::set_unexpected (std::unexpected_handler func)
{
std::unexpected_handler old =
(std::unexpected_handler) _keymgr_get_per_thread_data (KEYMGR_UNEXPECTED_HANDLER_KEY);
_keymgr_set_per_thread_data (KEYMGR_UNEXPECTED_HANDLER_KEY,func);
return old;
}
void
std::unexpected ()
{
std::unexpected_handler __unexpected_func =
(std::unexpected_handler) _keymgr_get_per_thread_data (KEYMGR_UNEXPECTED_HANDLER_KEY);
if (__unexpected_func == NULL)
terminate ();
else
__unexpected_func ();
}
#endif
struct cp_eh_info
{
__eh_info eh_info;
void *value;
void *type;
void (*cleanup)(void *, int);
bool caught;
cp_eh_info *next;
long handlers;
void *original_value;
};
extern "C" cp_eh_info **__get_eh_info ();
extern bool __is_pointer (void *);
extern "C" void *
__cp_exception_info (void)
{
return &((*__get_eh_info ())->value);
}
#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ())
extern "C" cp_eh_info *
__cp_eh_info (void)
{
cp_eh_info *p = CP_EH_INFO;
return p;
}
extern "C" cp_eh_info *
__start_cp_handler (void)
{
cp_eh_info *p = CP_EH_INFO;
p->caught = 1;
p->handlers++;
return p;
}
extern "C" void * malloc (size_t);
extern "C" void *
__eh_alloc (size_t size)
{
void *p = malloc (size);
if (p == 0)
terminate ();
return p;
}
extern "C" void free (void *);
extern "C" void
__eh_free (void *p)
{
free (p);
}
typedef void * (* rtimetype) (void);
extern "C" void *
__cplus_type_matcher (cp_eh_info *info, rtimetype match_info,
exception_descriptor *exception_table)
{
void *ret;
if (exception_table != NULL
&& exception_table->lang.language != EH_LANG_C_plus_plus)
return NULL;
if (match_info == CATCH_ALL_TYPE)
return info->value;
void *match_type = match_info ();
ret = __throw_type_match_rtti (match_type, info->type, info->original_value);
if (ret)
info->value = ret;
return ret;
}
extern "C" void
__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
{
cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info));
p->value = value;
p->type = type;
p->cleanup = cleanup;
p->handlers = 0;
p->caught = false;
p->original_value = value;
p->eh_info.match_function = __cplus_type_matcher;
p->eh_info.language = EH_LANG_C_plus_plus;
p->eh_info.version = 1;
cp_eh_info **q = __get_eh_info ();
p->next = *q;
*q = p;
}
extern "C" void
__cp_pop_exception (cp_eh_info *p)
{
cp_eh_info **q = __get_eh_info ();
--p->handlers;
if (p->handlers != 0
|| (p == *q && !p->caught))
return;
for (; *q; q = &((*q)->next))
if (*q == p)
break;
if (! *q)
terminate ();
*q = p->next;
if (p->cleanup)
p->cleanup (p->original_value, 2);
if (! __is_pointer (p->type))
__eh_free (p->original_value);
__eh_free (p);
}
extern "C" void
__uncatch_exception (void)
{
cp_eh_info *p = CP_EH_INFO;
if (p == 0)
terminate ();
p->caught = false;
}
extern "C" void
__check_eh_spec (int n, const void **spec)
{
cp_eh_info *p = CP_EH_INFO;
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti (spec[i], p->type, p->value))
throw;
}
try
{
std::unexpected ();
}
catch (...)
{
if (p != __exception_info)
{
p = __exception_info;
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti (spec[i], p->type, p->value))
throw;
}
}
const std::type_info &bad_exc = typeid (std::bad_exception);
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti (spec[i], &bad_exc, p->value))
throw std::bad_exception ();
}
terminate ();
}
}
extern "C" void
__throw_bad_cast (void)
{
throw std::bad_cast ();
}
extern "C" void
__throw_bad_typeid (void)
{
throw std::bad_typeid ();
}
bool
std::uncaught_exception ()
{
cp_eh_info *p = CP_EH_INFO;
return p && ! p->caught;
}
const char * std::exception::
what () const
{
return typeid (*this).name ();
}