blob: 1074828f74dca8339d0b3dbc74bddaa9757bb0a4 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/except.h>
20#include <pj/os.h>
21#include <pj/assert.h>
22#include <pj/log.h>
23#include <pj/errno.h>
Benny Prijono9df1d092006-07-03 01:09:20 +000024#include <pj/string.h>
Benny Prijono9033e312005-11-21 02:08:39 +000025
26static long thread_local_id = -1;
27
28#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
29 static const char *exception_id_names[PJ_MAX_EXCEPTION_ID];
30#else
31 /*
32 * Start from 1 (not 0)!!!
33 * Exception 0 is reserved for normal path of setjmp()!!!
34 */
35 static int last_exception_id = 1;
36#endif /* PJ_HAS_EXCEPTION_NAMES */
37
38
Benny Prijonod0d44f52005-11-21 16:57:02 +000039#if !defined(PJ_EXCEPTION_USE_WIN32_SEH) || PJ_EXCEPTION_USE_WIN32_SEH==0
Benny Prijono9033e312005-11-21 02:08:39 +000040PJ_DEF(void) pj_throw_exception_(int exception_id)
41{
42 struct pj_exception_state_t *handler;
43
44 handler = pj_thread_local_get(thread_local_id);
45 if (handler == NULL) {
Benny Prijono9df1d092006-07-03 01:09:20 +000046 PJ_LOG(1,("except.c", "!!!FATAL: unhandled exception %s!\n",
47 pj_exception_id_name(exception_id)));
Benny Prijono9033e312005-11-21 02:08:39 +000048 pj_assert(handler != NULL);
49 /* This will crash the system! */
50 }
51 pj_longjmp(handler->state, exception_id);
52}
53
54PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec)
55{
56 struct pj_exception_state_t *parent_handler = NULL;
57
58 if (thread_local_id == -1) {
59 pj_thread_local_alloc(&thread_local_id);
60 pj_assert(thread_local_id != -1);
61 }
62 parent_handler = pj_thread_local_get(thread_local_id);
63 rec->prev = parent_handler;
64 pj_thread_local_set(thread_local_id, rec);
65}
66
67PJ_DEF(void) pj_pop_exception_handler_(void)
68{
69 struct pj_exception_state_t *handler;
70
71 handler = pj_thread_local_get(thread_local_id);
72 pj_assert(handler != NULL);
73 pj_thread_local_set(thread_local_id, handler->prev);
74}
Benny Prijonod0d44f52005-11-21 16:57:02 +000075#endif
Benny Prijono9033e312005-11-21 02:08:39 +000076
77#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
78PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
79 pj_exception_id_t *id)
80{
81 unsigned i;
82
83 pj_enter_critical_section();
84
85 /*
86 * Start from 1 (not 0)!!!
87 * Exception 0 is reserved for normal path of setjmp()!!!
88 */
89 for (i=1; i<PJ_MAX_EXCEPTION_ID; ++i) {
90 if (exception_id_names[i] == NULL) {
91 exception_id_names[i] = name;
92 *id = i;
93 pj_leave_critical_section();
94 return PJ_SUCCESS;
95 }
96 }
97
98 pj_leave_critical_section();
99 return PJ_ETOOMANY;
100}
101
102PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
103{
104 /*
105 * Start from 1 (not 0)!!!
106 * Exception 0 is reserved for normal path of setjmp()!!!
107 */
108 PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, PJ_EINVAL);
109
110 pj_enter_critical_section();
111 exception_id_names[id] = NULL;
112 pj_leave_critical_section();
113
114 return PJ_SUCCESS;
115
116}
117
118PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
119{
Benny Prijono9df1d092006-07-03 01:09:20 +0000120 static char unknown_name[32];
121
Benny Prijono9033e312005-11-21 02:08:39 +0000122 /*
123 * Start from 1 (not 0)!!!
124 * Exception 0 is reserved for normal path of setjmp()!!!
125 */
126 PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, "<Invalid ID>");
127
Benny Prijono9df1d092006-07-03 01:09:20 +0000128 if (exception_id_names[id] == NULL) {
Benny Prijonoe85bc412006-07-29 20:29:24 +0000129 pj_ansi_snprintf(unknown_name, sizeof(unknown_name),
130 "exception %d", id);
Benny Prijono9df1d092006-07-03 01:09:20 +0000131 return unknown_name;
132 }
Benny Prijono9033e312005-11-21 02:08:39 +0000133
134 return exception_id_names[id];
135}
136
137#else /* PJ_HAS_EXCEPTION_NAMES */
138PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
139 pj_exception_id_t *id)
140{
141 PJ_ASSERT_RETURN(last_exception_id < PJ_MAX_EXCEPTION_ID-1, PJ_ETOOMANY);
142
Benny Prijono11852992006-03-18 12:28:03 +0000143 *id = last_exception_id++;
Benny Prijono9033e312005-11-21 02:08:39 +0000144 return PJ_SUCCESS;
145}
146
147PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
148{
149 return PJ_SUCCESS;
150}
151
152PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
153{
154 return "";
155}
156
157#endif /* PJ_HAS_EXCEPTION_NAMES */
158
159
160