blob: 308606c894beabb7c85f4f9cddbef505465c7ac6 [file] [log] [blame]
/*
* Copyright (C) Tildeslash Ltd. All rights reserved.
* Copyright (C) 1994,1995,1996,1997 by David R. Hanson.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
*
* You must obey the GNU Affero General Public License in all respects
* for all of the code used other than OpenSSL.
*/
#include "Config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "Str.h"
#include "Thread.h"
#include "system/System.h"
#include "Exception.h"
/**
* Implementation of the Exception interface. This implementation
* defines the Thread local Exception stack and all Exceptions used
* in the system. New Exceptions should also be defined in this class.
*
* This implementation is a minor modification of the Except code found
* in David R. Hanson's excellent book "C Interfaces and Implementations".
* See http://www.cs.princeton.edu/software/cii/
*
* @see http://www.mmonit.com/
* @file
*/
/* ----------------------------------------------------------- Definitions */
#define T Exception_T
/* Thread specific Exception stack */
ThreadData_T Exception_stack;
/* Placeholder for system exceptions */
Exception_T IOException = {"IOException"};
Exception_T AssertException = {"AssertException"};
Exception_T MemoryException = {"MemoryException"};
Exception_T NumberFormatException = {"NumberFormatException"};
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
/* --------------------------------------------------------------- Private */
static void init_once(void) { ThreadData_create(Exception_stack); }
/* ---------------------------------------------------------------- Public */
void Exception_init() { pthread_once(&once_control, init_once); }
void Exception_throw(const T *e, const char *func, const char *file, int line, const char *cause, ...) {
assert(e);
va_list ap;
Exception_Frame *p = ThreadData_get(Exception_stack);
if (p) {
p->exception = e;
p->func = func;
p->file = file;
p->line = line;
if (cause) {
va_start(ap, cause);
vsnprintf(p->message, EXCEPTION_MESSAGE_LENGTH, cause, ap);
va_end(ap);
}
pop_exception_stack;
longjmp(p->env, Exception_thrown);
} else if (cause) {
char message[EXCEPTION_MESSAGE_LENGTH + 1] = "?";
va_start(ap, cause);
vsnprintf(message, EXCEPTION_MESSAGE_LENGTH, cause, ap);
va_end(ap);
ABORT("%s: %s\n raised in %s at %s:%d\n", e->name, message, func ? func : "?", file ? file : "?", line);
} else {
ABORT("%s: 0x%p\n raised in %s at %s:%d\n", e->name, e, func ? func : "?", file ? file : "?", line);
}
}