1
by brian
clean slate |
1 |
/* Copyright (C) 2000 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
#include "mysys_priv.h" |
|
17 |
#include "mysys_err.h" |
|
18 |
#include <m_string.h> |
|
19 |
#include <stdarg.h> |
|
20 |
#include <m_ctype.h> |
|
21 |
||
22 |
/* Define some external variables for error handling */
|
|
23 |
||
24 |
/*
|
|
25 |
WARNING!
|
|
26 |
my_error family functions have to be used according following rules:
|
|
27 |
- if message have not parameters use my_message(ER_CODE, ER(ER_CODE), MYF(N))
|
|
28 |
- if message registered use my_error(ER_CODE, MYF(N), ...).
|
|
29 |
- With some special text of errror message use:
|
|
30 |
my_printf_error(ER_CODE, format, MYF(N), ...)
|
|
31 |
*/
|
|
32 |
||
33 |
char errbuff[NRERRBUFFS][ERRMSGSIZE]; |
|
34 |
||
35 |
/*
|
|
36 |
Message texts are registered into a linked list of 'my_err_head' structs.
|
|
37 |
Each struct contains (1.) an array of pointers to C character strings with
|
|
38 |
'\0' termination, (2.) the error number for the first message in the array
|
|
39 |
(array index 0) and (3.) the error number for the last message in the array
|
|
40 |
(array index (last - first)).
|
|
41 |
The array may contain gaps with NULL pointers and pointers to empty strings.
|
|
42 |
Both kinds of gaps will be translated to "Unknown error %d.", if my_error()
|
|
43 |
is called with a respective error number.
|
|
44 |
The list of header structs is sorted in increasing order of error numbers.
|
|
45 |
Negative error numbers are allowed. Overlap of error numbers is not allowed.
|
|
46 |
Not registered error numbers will be translated to "Unknown error %d.".
|
|
47 |
*/
|
|
48 |
static struct my_err_head |
|
49 |
{
|
|
50 |
struct my_err_head *meh_next; /* chain link */ |
|
51 |
const char **meh_errmsgs; /* error messages array */ |
|
52 |
int meh_first; /* error number matching array slot 0 */ |
|
53 |
int meh_last; /* error number matching last slot */ |
|
54 |
} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST}; |
|
55 |
||
56 |
static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; |
|
57 |
||
58 |
||
59 |
/*
|
|
60 |
Error message to user
|
|
61 |
||
62 |
SYNOPSIS
|
|
63 |
my_error()
|
|
64 |
nr Errno
|
|
65 |
MyFlags Flags
|
|
66 |
... variable list
|
|
67 |
*/
|
|
68 |
||
69 |
void my_error(int nr, myf MyFlags, ...) |
|
70 |
{
|
|
71 |
const char *format; |
|
72 |
struct my_err_head *meh_p; |
|
73 |
va_list args; |
|
74 |
char ebuff[ERRMSGSIZE + 20]; |
|
75 |
DBUG_ENTER("my_error"); |
|
76 |
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno)); |
|
77 |
||
78 |
/* Search for the error messages array, which could contain the message. */
|
|
79 |
for (meh_p= my_errmsgs_list; meh_p; meh_p= meh_p->meh_next) |
|
80 |
if (nr <= meh_p->meh_last) |
|
81 |
break; |
|
82 |
||
83 |
/* get the error message string. Default, if NULL or empty string (""). */
|
|
84 |
if (! (format= (meh_p && (nr >= meh_p->meh_first)) ? |
|
85 |
meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format) |
|
86 |
(void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr); |
|
87 |
else
|
|
88 |
{
|
|
89 |
va_start(args,MyFlags); |
|
90 |
(void) my_vsnprintf (ebuff, sizeof(ebuff), format, args); |
|
91 |
va_end(args); |
|
92 |
}
|
|
93 |
(*error_handler_hook)(nr, ebuff, MyFlags); |
|
94 |
DBUG_VOID_RETURN; |
|
95 |
}
|
|
96 |
||
97 |
||
98 |
/*
|
|
99 |
Error as printf
|
|
100 |
||
101 |
SYNOPSIS
|
|
102 |
my_printf_error()
|
|
103 |
error Errno
|
|
104 |
format Format string
|
|
105 |
MyFlags Flags
|
|
106 |
... variable list
|
|
107 |
*/
|
|
108 |
||
109 |
void my_printf_error(uint error, const char *format, myf MyFlags, ...) |
|
110 |
{
|
|
111 |
va_list args; |
|
112 |
char ebuff[ERRMSGSIZE+20]; |
|
113 |
DBUG_ENTER("my_printf_error"); |
|
114 |
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s", |
|
115 |
error, MyFlags, errno, format)); |
|
116 |
||
117 |
va_start(args,MyFlags); |
|
118 |
(void) my_vsnprintf (ebuff, sizeof(ebuff), format, args); |
|
119 |
va_end(args); |
|
120 |
(*error_handler_hook)(error, ebuff, MyFlags); |
|
121 |
DBUG_VOID_RETURN; |
|
122 |
}
|
|
123 |
||
124 |
/*
|
|
125 |
Give message using error_handler_hook
|
|
126 |
||
127 |
SYNOPSIS
|
|
128 |
my_message()
|
|
129 |
error Errno
|
|
130 |
str Error message
|
|
131 |
MyFlags Flags
|
|
132 |
*/
|
|
133 |
||
134 |
void my_message(uint error, const char *str, register myf MyFlags) |
|
135 |
{
|
|
136 |
(*error_handler_hook)(error, str, MyFlags); |
|
137 |
}
|
|
138 |
||
139 |
||
140 |
/*
|
|
141 |
Register error messages for use with my_error().
|
|
142 |
||
143 |
SYNOPSIS
|
|
144 |
my_error_register()
|
|
145 |
errmsgs array of pointers to error messages
|
|
146 |
first error number of first message in the array
|
|
147 |
last error number of last message in the array
|
|
148 |
||
149 |
DESCRIPTION
|
|
150 |
The pointer array is expected to contain addresses to NUL-terminated
|
|
151 |
C character strings. The array contains (last - first + 1) pointers.
|
|
152 |
NULL pointers and empty strings ("") are allowed. These will be mapped to
|
|
153 |
"Unknown error" when my_error() is called with a matching error number.
|
|
154 |
This function registers the error numbers 'first' to 'last'.
|
|
155 |
No overlapping with previously registered error numbers is allowed.
|
|
156 |
||
157 |
RETURN
|
|
158 |
0 OK
|
|
159 |
!= 0 Error
|
|
160 |
*/
|
|
161 |
||
162 |
int my_error_register(const char **errmsgs, int first, int last) |
|
163 |
{
|
|
164 |
struct my_err_head *meh_p; |
|
165 |
struct my_err_head **search_meh_pp; |
|
166 |
||
167 |
/* Allocate a new header structure. */
|
|
168 |
if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head), |
|
169 |
MYF(MY_WME)))) |
|
170 |
return 1; |
|
171 |
meh_p->meh_errmsgs= errmsgs; |
|
172 |
meh_p->meh_first= first; |
|
173 |
meh_p->meh_last= last; |
|
174 |
||
175 |
/* Search for the right position in the list. */
|
|
176 |
for (search_meh_pp= &my_errmsgs_list; |
|
177 |
*search_meh_pp; |
|
178 |
search_meh_pp= &(*search_meh_pp)->meh_next) |
|
179 |
{
|
|
180 |
if ((*search_meh_pp)->meh_last > first) |
|
181 |
break; |
|
182 |
}
|
|
183 |
||
184 |
/* Error numbers must be unique. No overlapping is allowed. */
|
|
185 |
if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) |
|
186 |
{
|
|
187 |
my_free((uchar*)meh_p, MYF(0)); |
|
188 |
return 1; |
|
189 |
}
|
|
190 |
||
191 |
/* Insert header into the chain. */
|
|
192 |
meh_p->meh_next= *search_meh_pp; |
|
193 |
*search_meh_pp= meh_p; |
|
194 |
return 0; |
|
195 |
}
|
|
196 |
||
197 |
||
198 |
/*
|
|
199 |
Unregister formerly registered error messages.
|
|
200 |
||
201 |
SYNOPSIS
|
|
202 |
my_error_unregister()
|
|
203 |
first error number of first message
|
|
204 |
last error number of last message
|
|
205 |
||
206 |
DESCRIPTION
|
|
207 |
This function unregisters the error numbers 'first' to 'last'.
|
|
208 |
These must have been previously registered by my_error_register().
|
|
209 |
'first' and 'last' must exactly match the registration.
|
|
210 |
If a matching registration is present, the header is removed from the
|
|
211 |
list and the pointer to the error messages pointers array is returned.
|
|
212 |
Otherwise, NULL is returned.
|
|
213 |
||
214 |
RETURN
|
|
215 |
non-NULL OK, returns address of error messages pointers array.
|
|
216 |
NULL Error, no such number range registered.
|
|
217 |
*/
|
|
218 |
||
219 |
const char **my_error_unregister(int first, int last) |
|
220 |
{
|
|
221 |
struct my_err_head *meh_p; |
|
222 |
struct my_err_head **search_meh_pp; |
|
223 |
const char **errmsgs; |
|
224 |
||
225 |
/* Search for the registration in the list. */
|
|
226 |
for (search_meh_pp= &my_errmsgs_list; |
|
227 |
*search_meh_pp; |
|
228 |
search_meh_pp= &(*search_meh_pp)->meh_next) |
|
229 |
{
|
|
230 |
if (((*search_meh_pp)->meh_first == first) && |
|
231 |
((*search_meh_pp)->meh_last == last)) |
|
232 |
break; |
|
233 |
}
|
|
234 |
if (! *search_meh_pp) |
|
235 |
return NULL; |
|
236 |
||
237 |
/* Remove header from the chain. */
|
|
238 |
meh_p= *search_meh_pp; |
|
239 |
*search_meh_pp= meh_p->meh_next; |
|
240 |
||
241 |
/* Save the return value and free the header. */
|
|
242 |
errmsgs= meh_p->meh_errmsgs; |
|
243 |
my_free((uchar*) meh_p, MYF(0)); |
|
244 |
||
245 |
return errmsgs; |
|
246 |
}
|
|
247 |
||
248 |
||
249 |
void my_error_unregister_all(void) |
|
250 |
{
|
|
251 |
struct my_err_head *list, *next; |
|
252 |
for (list= my_errmsgs_globerrs.meh_next; list; list= next) |
|
253 |
{
|
|
254 |
next= list->meh_next; |
|
255 |
my_free((uchar*) list, MYF(0)); |
|
256 |
}
|
|
257 |
my_errmsgs_list= &my_errmsgs_globerrs; |
|
258 |
}
|