src/SDL_error.c
changeset 0 74212992fb08
child 1 cf2af46e9e2a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/SDL_error.c	Thu Apr 26 16:45:43 2001 +0000
     1.3 @@ -0,0 +1,340 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@devolution.com
    1.24 +*/
    1.25 +
    1.26 +#ifdef SAVE_RCSID
    1.27 +static char rcsid =
    1.28 + "@(#) $Id$";
    1.29 +#endif
    1.30 +
    1.31 +/* Simple error handling in SDL */
    1.32 +
    1.33 +#include <stdio.h>
    1.34 +#include <stdlib.h>
    1.35 +#include <stdarg.h>
    1.36 +#include <string.h>
    1.37 +
    1.38 +#include "SDL_types.h"
    1.39 +#include "SDL_getenv.h"
    1.40 +#include "SDL_error.h"
    1.41 +#include "SDL_error_c.h"
    1.42 +#ifndef DISABLE_THREADS
    1.43 +#include "SDL_thread_c.h"
    1.44 +#endif
    1.45 +
    1.46 +#ifdef DISABLE_THREADS
    1.47 +/* The default (non-thread-safe) global error variable */
    1.48 +static SDL_error SDL_global_error;
    1.49 +
    1.50 +#define SDL_GetErrBuf()	(&SDL_global_error)
    1.51 +#endif /* DISABLE_THREADS */
    1.52 +
    1.53 +#define SDL_ERRBUFIZE	1024
    1.54 +
    1.55 +/* Private functions */
    1.56 +
    1.57 +static void SDL_LookupString(const Uint8 *key, Uint16 *buf, int buflen)
    1.58 +{
    1.59 +	/* FIXME: Add code to lookup key in language string hash-table */
    1.60 +
    1.61 +	/* Key not found in language string hash-table */
    1.62 +	while ( *key && (--buflen > 0) ) {
    1.63 +		*buf++ = *key++;
    1.64 +	}
    1.65 +	*buf = 0;	/* NULL terminate string */
    1.66 +}
    1.67 +
    1.68 +/* Public functions */
    1.69 +
    1.70 +void SDL_SetError (const char *fmt, ...)
    1.71 +{
    1.72 +	va_list ap;
    1.73 +	SDL_error *error;
    1.74 +
    1.75 +	/* Copy in the key, mark error as valid */
    1.76 +	error = SDL_GetErrBuf();
    1.77 +	error->error = 1;
    1.78 +	strncpy((char *)error->key, fmt, sizeof(error->key));
    1.79 +	error->key[sizeof(error->key)-1] = '\0';
    1.80 +
    1.81 +	va_start(ap, fmt);
    1.82 +	error->argc = 0;
    1.83 +	while ( *fmt ) {
    1.84 +		if ( *fmt++ == '%' ) {
    1.85 +			switch (*fmt++) {
    1.86 +			    case 0:  /* Malformed format string.. */
    1.87 +				--fmt;
    1.88 +				break;
    1.89 +#if 0	/* What is a character anyway?  (UNICODE issues) */
    1.90 +			    case 'c':
    1.91 +				error->args[error->argc++].value_c =
    1.92 +						va_arg(ap, unsigned char);
    1.93 +				break;
    1.94 +#endif
    1.95 +			    case 'd':
    1.96 +				error->args[error->argc++].value_i =
    1.97 +							va_arg(ap, int);
    1.98 +				break;
    1.99 +			    case 'f':
   1.100 +				error->args[error->argc++].value_f =
   1.101 +							va_arg(ap, double);
   1.102 +				break;
   1.103 +			    case 'p':
   1.104 +				error->args[error->argc++].value_ptr =
   1.105 +							va_arg(ap, void *);
   1.106 +				break;
   1.107 +			    case 's':
   1.108 +				{
   1.109 +				  int index = error->argc;
   1.110 +				  strncpy((char *)error->args[index].buf,
   1.111 +					va_arg(ap, char *), ERR_MAX_STRLEN);
   1.112 +				  error->args[index].buf[ERR_MAX_STRLEN-1] = 0;
   1.113 +				  error->argc++;
   1.114 +				}
   1.115 +				break;
   1.116 +			    default:
   1.117 +				break;
   1.118 +			}
   1.119 +			if ( error->argc >= ERR_MAX_ARGS ) {
   1.120 +				break;
   1.121 +			}
   1.122 +		}
   1.123 +	}
   1.124 +	va_end(ap);
   1.125 +
   1.126 +	/* If we are in debug mode, print out an error message */
   1.127 +#ifdef DEBUG_ERROR
   1.128 +	fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
   1.129 +#else
   1.130 +	if ( getenv("SDL_DEBUG") ) {
   1.131 +		fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
   1.132 +	}
   1.133 +#endif
   1.134 +}
   1.135 +
   1.136 +/* Print out an integer value to a UNICODE buffer */
   1.137 +static int PrintInt(Uint16 *str, unsigned int maxlen, int value)
   1.138 +{
   1.139 +	char tmp[128];
   1.140 +	int len, i;
   1.141 +
   1.142 +	sprintf(tmp, "%d", value);
   1.143 +	len = 0;
   1.144 +	if ( strlen(tmp) < maxlen ) {
   1.145 +		for ( i=0; tmp[i]; ++i ) {
   1.146 +			*str++ = tmp[i];
   1.147 +			++len;
   1.148 +		}
   1.149 +	}
   1.150 +	return(len);
   1.151 +}
   1.152 +/* Print out a double value to a UNICODE buffer */
   1.153 +static int PrintDouble(Uint16 *str, unsigned int maxlen, double value)
   1.154 +{
   1.155 +	char tmp[128];
   1.156 +	int len, i;
   1.157 +
   1.158 +	sprintf(tmp, "%f", value);
   1.159 +	len = 0;
   1.160 +	if ( strlen(tmp) < maxlen ) {
   1.161 +		for ( i=0; tmp[i]; ++i ) {
   1.162 +			*str++ = tmp[i];
   1.163 +			++len;
   1.164 +		}
   1.165 +	}
   1.166 +	return(len);
   1.167 +}
   1.168 +/* Print out a pointer value to a UNICODE buffer */
   1.169 +static int PrintPointer(Uint16 *str, unsigned int maxlen, void *value)
   1.170 +{
   1.171 +	char tmp[128];
   1.172 +	int len, i;
   1.173 +
   1.174 +	sprintf(tmp, "%p", value);
   1.175 +	len = 0;
   1.176 +	if ( strlen(tmp) < maxlen ) {
   1.177 +		for ( i=0; tmp[i]; ++i ) {
   1.178 +			*str++ = tmp[i];
   1.179 +			++len;
   1.180 +		}
   1.181 +	}
   1.182 +	return(len);
   1.183 +}
   1.184 +
   1.185 +/* This function has a bit more overhead than most error functions
   1.186 +   so that it supports internationalization and thread-safe errors.
   1.187 +*/
   1.188 +Uint16 *SDL_GetErrorMsgUNICODE(Uint16 *errstr, unsigned int maxlen)
   1.189 +{
   1.190 +	SDL_error *error;
   1.191 +
   1.192 +	/* Clear the error string */
   1.193 +	*errstr = 0; --maxlen;
   1.194 +
   1.195 +	/* Get the thread-safe error, and print it out */
   1.196 +	error = SDL_GetErrBuf();
   1.197 +	if ( error->error ) {
   1.198 +		Uint16 translated[ERR_MAX_STRLEN], *fmt, *msg;
   1.199 +		int len;
   1.200 +		int argi;
   1.201 +
   1.202 +		/* Print out the UNICODE error message */
   1.203 +		SDL_LookupString(error->key, translated, sizeof(translated));
   1.204 +		msg = errstr;
   1.205 +		argi = 0;
   1.206 +		for ( fmt=translated; *fmt && (maxlen > 0); ) {
   1.207 +			if ( *fmt == '%' ) {
   1.208 +				switch (fmt[1]) {
   1.209 +				    case 'S':	/* Special SKIP operand */
   1.210 +					argi += (fmt[2] - '0');
   1.211 +					++fmt;
   1.212 +					break;
   1.213 +				    case '%':
   1.214 +					*msg++ = '%';
   1.215 +					maxlen -= 1;
   1.216 +					break;
   1.217 +#if 0	/* What is a character anyway?  (UNICODE issues) */
   1.218 +				    case 'c':
   1.219 +                                        *msg++ = (unsigned char)
   1.220 +					         error->args[argi++].value_c;
   1.221 +					maxlen -= 1;
   1.222 +					break;
   1.223 +#endif
   1.224 +				    case 'd':
   1.225 +					len = PrintInt(msg, maxlen,
   1.226 +						error->args[argi++].value_i);
   1.227 +					msg += len;
   1.228 +					maxlen -= len;
   1.229 +					break;
   1.230 +				    case 'f':
   1.231 +					len = PrintDouble(msg, maxlen,
   1.232 +						error->args[argi++].value_f);
   1.233 +					msg += len;
   1.234 +					maxlen -= len;
   1.235 +					break;
   1.236 +				    case 'p':
   1.237 +					len = PrintPointer(msg, maxlen,
   1.238 +						error->args[argi++].value_ptr);
   1.239 +					msg += len;
   1.240 +					maxlen -= len;
   1.241 +					break;
   1.242 +				    case 's': /* UNICODE string */
   1.243 +					{ Uint16 buf[ERR_MAX_STRLEN], *str;
   1.244 +					  SDL_LookupString(error->args[argi++].buf, buf, sizeof(buf));
   1.245 +					  str = buf;
   1.246 +					  while ( *str && (maxlen > 0) ) {
   1.247 +						*msg++ = *str++;
   1.248 +						maxlen -= 1;
   1.249 +					  }
   1.250 +					}
   1.251 +					break;
   1.252 +				}
   1.253 +				fmt += 2;
   1.254 +			} else {
   1.255 +				*msg++ = *fmt++;
   1.256 +				maxlen -= 1;
   1.257 +			}
   1.258 +		}
   1.259 +		*msg = 0;	/* NULL terminate the string */
   1.260 +	}
   1.261 +	return(errstr);
   1.262 +}
   1.263 +
   1.264 +Uint8 *SDL_GetErrorMsg(Uint8 *errstr, unsigned int maxlen)
   1.265 +{
   1.266 +	Uint16 *errstr16;
   1.267 +	unsigned int i;
   1.268 +
   1.269 +	/* Allocate the UNICODE buffer */
   1.270 +	errstr16 = (Uint16 *)malloc(maxlen * (sizeof *errstr16));
   1.271 +	if ( ! errstr16 ) {
   1.272 +		strncpy((char *)errstr, "Out of memory", maxlen);
   1.273 +		errstr[maxlen-1] = '\0';
   1.274 +		return(errstr);
   1.275 +	}
   1.276 +
   1.277 +	/* Get the error message */
   1.278 +	SDL_GetErrorMsgUNICODE(errstr16, maxlen);
   1.279 +
   1.280 +	/* Convert from UNICODE to Latin1 encoding */
   1.281 +	for ( i=0; i<maxlen; ++i ) {
   1.282 +		errstr[i] = (Uint8)errstr16[i];
   1.283 +	}
   1.284 +
   1.285 +	/* Free UNICODE buffer (if necessary) */
   1.286 +	free(errstr16);
   1.287 +
   1.288 +	return(errstr);
   1.289 +}
   1.290 +
   1.291 +/* Available for backwards compatibility */
   1.292 +char *SDL_GetError (void)
   1.293 +{
   1.294 +	static char errmsg[SDL_ERRBUFIZE];
   1.295 +
   1.296 +	return((char *)SDL_GetErrorMsg((unsigned char *)errmsg, SDL_ERRBUFIZE));
   1.297 +}
   1.298 +
   1.299 +void SDL_ClearError(void)
   1.300 +{
   1.301 +	SDL_error *error;
   1.302 +
   1.303 +	error = SDL_GetErrBuf();
   1.304 +	error->error = 0;
   1.305 +}
   1.306 +
   1.307 +/* Very common errors go here */
   1.308 +void SDL_Error(SDL_errorcode code)
   1.309 +{
   1.310 +	switch (code) {
   1.311 +		case SDL_ENOMEM:
   1.312 +			SDL_SetError("Out of memory");
   1.313 +			break;
   1.314 +		case SDL_EFREAD:
   1.315 +			SDL_SetError("Error reading from datastream");
   1.316 +			break;
   1.317 +		case SDL_EFWRITE:
   1.318 +			SDL_SetError("Error writing to datastream");
   1.319 +			break;
   1.320 +		case SDL_EFSEEK:
   1.321 +			SDL_SetError("Error seeking in datastream");
   1.322 +			break;
   1.323 +		default:
   1.324 +			SDL_SetError("Unknown SDL error");
   1.325 +			break;
   1.326 +	}
   1.327 +}
   1.328 +
   1.329 +#ifdef TEST_ERROR
   1.330 +int main(int argc, char *argv[])
   1.331 +{
   1.332 +	char buffer[BUFSIZ+1];
   1.333 +
   1.334 +	SDL_SetError("Hi there!");
   1.335 +	printf("Error 1: %s\n", SDL_GetError());
   1.336 +	SDL_ClearError();
   1.337 +	memset(buffer, '1', BUFSIZ);
   1.338 +	buffer[BUFSIZ] = 0;
   1.339 +	SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
   1.340 +	printf("Error 2: %s\n", SDL_GetError());
   1.341 +	exit(0);
   1.342 +}
   1.343 +#endif