comparison src/SDL_error.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children cf2af46e9e2a
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@devolution.com
21 */
22
23 #ifdef SAVE_RCSID
24 static char rcsid =
25 "@(#) $Id$";
26 #endif
27
28 /* Simple error handling in SDL */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34
35 #include "SDL_types.h"
36 #include "SDL_getenv.h"
37 #include "SDL_error.h"
38 #include "SDL_error_c.h"
39 #ifndef DISABLE_THREADS
40 #include "SDL_thread_c.h"
41 #endif
42
43 #ifdef DISABLE_THREADS
44 /* The default (non-thread-safe) global error variable */
45 static SDL_error SDL_global_error;
46
47 #define SDL_GetErrBuf() (&SDL_global_error)
48 #endif /* DISABLE_THREADS */
49
50 #define SDL_ERRBUFIZE 1024
51
52 /* Private functions */
53
54 static void SDL_LookupString(const Uint8 *key, Uint16 *buf, int buflen)
55 {
56 /* FIXME: Add code to lookup key in language string hash-table */
57
58 /* Key not found in language string hash-table */
59 while ( *key && (--buflen > 0) ) {
60 *buf++ = *key++;
61 }
62 *buf = 0; /* NULL terminate string */
63 }
64
65 /* Public functions */
66
67 void SDL_SetError (const char *fmt, ...)
68 {
69 va_list ap;
70 SDL_error *error;
71
72 /* Copy in the key, mark error as valid */
73 error = SDL_GetErrBuf();
74 error->error = 1;
75 strncpy((char *)error->key, fmt, sizeof(error->key));
76 error->key[sizeof(error->key)-1] = '\0';
77
78 va_start(ap, fmt);
79 error->argc = 0;
80 while ( *fmt ) {
81 if ( *fmt++ == '%' ) {
82 switch (*fmt++) {
83 case 0: /* Malformed format string.. */
84 --fmt;
85 break;
86 #if 0 /* What is a character anyway? (UNICODE issues) */
87 case 'c':
88 error->args[error->argc++].value_c =
89 va_arg(ap, unsigned char);
90 break;
91 #endif
92 case 'd':
93 error->args[error->argc++].value_i =
94 va_arg(ap, int);
95 break;
96 case 'f':
97 error->args[error->argc++].value_f =
98 va_arg(ap, double);
99 break;
100 case 'p':
101 error->args[error->argc++].value_ptr =
102 va_arg(ap, void *);
103 break;
104 case 's':
105 {
106 int index = error->argc;
107 strncpy((char *)error->args[index].buf,
108 va_arg(ap, char *), ERR_MAX_STRLEN);
109 error->args[index].buf[ERR_MAX_STRLEN-1] = 0;
110 error->argc++;
111 }
112 break;
113 default:
114 break;
115 }
116 if ( error->argc >= ERR_MAX_ARGS ) {
117 break;
118 }
119 }
120 }
121 va_end(ap);
122
123 /* If we are in debug mode, print out an error message */
124 #ifdef DEBUG_ERROR
125 fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
126 #else
127 if ( getenv("SDL_DEBUG") ) {
128 fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
129 }
130 #endif
131 }
132
133 /* Print out an integer value to a UNICODE buffer */
134 static int PrintInt(Uint16 *str, unsigned int maxlen, int value)
135 {
136 char tmp[128];
137 int len, i;
138
139 sprintf(tmp, "%d", value);
140 len = 0;
141 if ( strlen(tmp) < maxlen ) {
142 for ( i=0; tmp[i]; ++i ) {
143 *str++ = tmp[i];
144 ++len;
145 }
146 }
147 return(len);
148 }
149 /* Print out a double value to a UNICODE buffer */
150 static int PrintDouble(Uint16 *str, unsigned int maxlen, double value)
151 {
152 char tmp[128];
153 int len, i;
154
155 sprintf(tmp, "%f", value);
156 len = 0;
157 if ( strlen(tmp) < maxlen ) {
158 for ( i=0; tmp[i]; ++i ) {
159 *str++ = tmp[i];
160 ++len;
161 }
162 }
163 return(len);
164 }
165 /* Print out a pointer value to a UNICODE buffer */
166 static int PrintPointer(Uint16 *str, unsigned int maxlen, void *value)
167 {
168 char tmp[128];
169 int len, i;
170
171 sprintf(tmp, "%p", value);
172 len = 0;
173 if ( strlen(tmp) < maxlen ) {
174 for ( i=0; tmp[i]; ++i ) {
175 *str++ = tmp[i];
176 ++len;
177 }
178 }
179 return(len);
180 }
181
182 /* This function has a bit more overhead than most error functions
183 so that it supports internationalization and thread-safe errors.
184 */
185 Uint16 *SDL_GetErrorMsgUNICODE(Uint16 *errstr, unsigned int maxlen)
186 {
187 SDL_error *error;
188
189 /* Clear the error string */
190 *errstr = 0; --maxlen;
191
192 /* Get the thread-safe error, and print it out */
193 error = SDL_GetErrBuf();
194 if ( error->error ) {
195 Uint16 translated[ERR_MAX_STRLEN], *fmt, *msg;
196 int len;
197 int argi;
198
199 /* Print out the UNICODE error message */
200 SDL_LookupString(error->key, translated, sizeof(translated));
201 msg = errstr;
202 argi = 0;
203 for ( fmt=translated; *fmt && (maxlen > 0); ) {
204 if ( *fmt == '%' ) {
205 switch (fmt[1]) {
206 case 'S': /* Special SKIP operand */
207 argi += (fmt[2] - '0');
208 ++fmt;
209 break;
210 case '%':
211 *msg++ = '%';
212 maxlen -= 1;
213 break;
214 #if 0 /* What is a character anyway? (UNICODE issues) */
215 case 'c':
216 *msg++ = (unsigned char)
217 error->args[argi++].value_c;
218 maxlen -= 1;
219 break;
220 #endif
221 case 'd':
222 len = PrintInt(msg, maxlen,
223 error->args[argi++].value_i);
224 msg += len;
225 maxlen -= len;
226 break;
227 case 'f':
228 len = PrintDouble(msg, maxlen,
229 error->args[argi++].value_f);
230 msg += len;
231 maxlen -= len;
232 break;
233 case 'p':
234 len = PrintPointer(msg, maxlen,
235 error->args[argi++].value_ptr);
236 msg += len;
237 maxlen -= len;
238 break;
239 case 's': /* UNICODE string */
240 { Uint16 buf[ERR_MAX_STRLEN], *str;
241 SDL_LookupString(error->args[argi++].buf, buf, sizeof(buf));
242 str = buf;
243 while ( *str && (maxlen > 0) ) {
244 *msg++ = *str++;
245 maxlen -= 1;
246 }
247 }
248 break;
249 }
250 fmt += 2;
251 } else {
252 *msg++ = *fmt++;
253 maxlen -= 1;
254 }
255 }
256 *msg = 0; /* NULL terminate the string */
257 }
258 return(errstr);
259 }
260
261 Uint8 *SDL_GetErrorMsg(Uint8 *errstr, unsigned int maxlen)
262 {
263 Uint16 *errstr16;
264 unsigned int i;
265
266 /* Allocate the UNICODE buffer */
267 errstr16 = (Uint16 *)malloc(maxlen * (sizeof *errstr16));
268 if ( ! errstr16 ) {
269 strncpy((char *)errstr, "Out of memory", maxlen);
270 errstr[maxlen-1] = '\0';
271 return(errstr);
272 }
273
274 /* Get the error message */
275 SDL_GetErrorMsgUNICODE(errstr16, maxlen);
276
277 /* Convert from UNICODE to Latin1 encoding */
278 for ( i=0; i<maxlen; ++i ) {
279 errstr[i] = (Uint8)errstr16[i];
280 }
281
282 /* Free UNICODE buffer (if necessary) */
283 free(errstr16);
284
285 return(errstr);
286 }
287
288 /* Available for backwards compatibility */
289 char *SDL_GetError (void)
290 {
291 static char errmsg[SDL_ERRBUFIZE];
292
293 return((char *)SDL_GetErrorMsg((unsigned char *)errmsg, SDL_ERRBUFIZE));
294 }
295
296 void SDL_ClearError(void)
297 {
298 SDL_error *error;
299
300 error = SDL_GetErrBuf();
301 error->error = 0;
302 }
303
304 /* Very common errors go here */
305 void SDL_Error(SDL_errorcode code)
306 {
307 switch (code) {
308 case SDL_ENOMEM:
309 SDL_SetError("Out of memory");
310 break;
311 case SDL_EFREAD:
312 SDL_SetError("Error reading from datastream");
313 break;
314 case SDL_EFWRITE:
315 SDL_SetError("Error writing to datastream");
316 break;
317 case SDL_EFSEEK:
318 SDL_SetError("Error seeking in datastream");
319 break;
320 default:
321 SDL_SetError("Unknown SDL error");
322 break;
323 }
324 }
325
326 #ifdef TEST_ERROR
327 int main(int argc, char *argv[])
328 {
329 char buffer[BUFSIZ+1];
330
331 SDL_SetError("Hi there!");
332 printf("Error 1: %s\n", SDL_GetError());
333 SDL_ClearError();
334 memset(buffer, '1', BUFSIZ);
335 buffer[BUFSIZ] = 0;
336 SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
337 printf("Error 2: %s\n", SDL_GetError());
338 exit(0);
339 }
340 #endif