src/SDL_error.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 06 May 2004 15:55:06 +0000
changeset 886 05c551e5bc64
parent 769 b8d311d90021
child 1172 f69f4d25fb20
permissions -rw-r--r--
Date: Sat, 24 Apr 2004 15:13:32 +0300
From: "Mike Gorchak"
Subject: SDL updates for the QNX6

1. Updated the README.QNX
2. Updated libtool scripts, which are shipped with SDL for QNX6 support.
3. Added some code to support the new QNX 6.3.0, which is in beta now.
4. Added code to detect the hw features, which driver supports.
5. Added hw alpha blits code.
6. Fixed bug when application switches to fullscreen more the 2 times. (afte\
r that window becames always stay on top).
7. Updated a bit README for the tests.
8. Added information about acceleration show in the testalpha.c test.
9. Added small fixes to the testoverlay2.c test.
10. Added alpha and cc+alpha blits benchmarks to the testvidinfo.c test.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2004 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@libsdl.org
    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 #ifdef __CYGWIN__
    51 #define DISABLE_STDIO
    52 #endif
    53 
    54 #define SDL_ERRBUFIZE	1024
    55 
    56 /* Private functions */
    57 
    58 static void SDL_LookupString(const Uint8 *key, Uint16 *buf, int buflen)
    59 {
    60 	/* FIXME: Add code to lookup key in language string hash-table */
    61 
    62 	/* Key not found in language string hash-table */
    63 	while ( *key && (--buflen > 0) ) {
    64 		*buf++ = *key++;
    65 	}
    66 	*buf = 0;	/* NULL terminate string */
    67 }
    68 
    69 /* Public functions */
    70 
    71 void SDL_SetError (const char *fmt, ...)
    72 {
    73 	va_list ap;
    74 	SDL_error *error;
    75 
    76 	/* Copy in the key, mark error as valid */
    77 	error = SDL_GetErrBuf();
    78 	error->error = 1;
    79 	strncpy((char *)error->key, fmt, sizeof(error->key));
    80 	error->key[sizeof(error->key)-1] = '\0';
    81 
    82 	va_start(ap, fmt);
    83 	error->argc = 0;
    84 	while ( *fmt ) {
    85 		if ( *fmt++ == '%' ) {
    86 			switch (*fmt++) {
    87 			    case 0:  /* Malformed format string.. */
    88 				--fmt;
    89 				break;
    90 #if 0	/* What is a character anyway?  (UNICODE issues) */
    91 			    case 'c':
    92 				error->args[error->argc++].value_c =
    93 						va_arg(ap, unsigned char);
    94 				break;
    95 #endif
    96 			    case 'd':
    97 				error->args[error->argc++].value_i =
    98 							va_arg(ap, int);
    99 				break;
   100 			    case 'f':
   101 				error->args[error->argc++].value_f =
   102 							va_arg(ap, double);
   103 				break;
   104 			    case 'p':
   105 				error->args[error->argc++].value_ptr =
   106 							va_arg(ap, void *);
   107 				break;
   108 			    case 's':
   109 				{
   110 				  int index = error->argc;
   111 				  strncpy((char *)error->args[index].buf,
   112 					va_arg(ap, char *), ERR_MAX_STRLEN);
   113 				  error->args[index].buf[ERR_MAX_STRLEN-1] = 0;
   114 				  error->argc++;
   115 				}
   116 				break;
   117 			    default:
   118 				break;
   119 			}
   120 			if ( error->argc >= ERR_MAX_ARGS ) {
   121 				break;
   122 			}
   123 		}
   124 	}
   125 	va_end(ap);
   126 
   127 #ifndef DISABLE_STDIO
   128 	/* If we are in debug mode, print out an error message */
   129 #ifdef DEBUG_ERROR
   130 	fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
   131 #else
   132 	if ( getenv("SDL_DEBUG") ) {
   133 		fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
   134 	}
   135 #endif
   136 #endif /* !DISABLE_STDIO */
   137 }
   138 
   139 /* Print out an integer value to a UNICODE buffer */
   140 static int PrintInt(Uint16 *str, unsigned int maxlen, int value)
   141 {
   142 	char tmp[128];
   143 	int len, i;
   144 
   145 	sprintf(tmp, "%d", value);
   146 	len = 0;
   147 	if ( strlen(tmp) < maxlen ) {
   148 		for ( i=0; tmp[i]; ++i ) {
   149 			*str++ = tmp[i];
   150 			++len;
   151 		}
   152 	}
   153 	return(len);
   154 }
   155 /* Print out a double value to a UNICODE buffer */
   156 static int PrintDouble(Uint16 *str, unsigned int maxlen, double value)
   157 {
   158 	char tmp[128];
   159 	int len, i;
   160 
   161 	sprintf(tmp, "%f", value);
   162 	len = 0;
   163 	if ( strlen(tmp) < maxlen ) {
   164 		for ( i=0; tmp[i]; ++i ) {
   165 			*str++ = tmp[i];
   166 			++len;
   167 		}
   168 	}
   169 	return(len);
   170 }
   171 /* Print out a pointer value to a UNICODE buffer */
   172 static int PrintPointer(Uint16 *str, unsigned int maxlen, void *value)
   173 {
   174 	char tmp[128];
   175 	int len, i;
   176 
   177 	sprintf(tmp, "%p", value);
   178 	len = 0;
   179 	if ( strlen(tmp) < maxlen ) {
   180 		for ( i=0; tmp[i]; ++i ) {
   181 			*str++ = tmp[i];
   182 			++len;
   183 		}
   184 	}
   185 	return(len);
   186 }
   187 
   188 /* This function has a bit more overhead than most error functions
   189    so that it supports internationalization and thread-safe errors.
   190 */
   191 Uint16 *SDL_GetErrorMsgUNICODE(Uint16 *errstr, unsigned int maxlen)
   192 {
   193 	SDL_error *error;
   194 
   195 	/* Clear the error string */
   196 	*errstr = 0; --maxlen;
   197 
   198 	/* Get the thread-safe error, and print it out */
   199 	error = SDL_GetErrBuf();
   200 	if ( error->error ) {
   201 		Uint16 translated[ERR_MAX_STRLEN], *fmt, *msg;
   202 		int len;
   203 		int argi;
   204 
   205 		/* Print out the UNICODE error message */
   206 		SDL_LookupString(error->key, translated, sizeof(translated));
   207 		msg = errstr;
   208 		argi = 0;
   209 		for ( fmt=translated; *fmt && (maxlen > 0); ) {
   210 			if ( *fmt == '%' ) {
   211 				switch (fmt[1]) {
   212 				    case 'S':	/* Special SKIP operand */
   213 					argi += (fmt[2] - '0');
   214 					++fmt;
   215 					break;
   216 				    case '%':
   217 					*msg++ = '%';
   218 					maxlen -= 1;
   219 					break;
   220 #if 0	/* What is a character anyway?  (UNICODE issues) */
   221 				    case 'c':
   222                                         *msg++ = (unsigned char)
   223 					         error->args[argi++].value_c;
   224 					maxlen -= 1;
   225 					break;
   226 #endif
   227 				    case 'd':
   228 					len = PrintInt(msg, maxlen,
   229 						error->args[argi++].value_i);
   230 					msg += len;
   231 					maxlen -= len;
   232 					break;
   233 				    case 'f':
   234 					len = PrintDouble(msg, maxlen,
   235 						error->args[argi++].value_f);
   236 					msg += len;
   237 					maxlen -= len;
   238 					break;
   239 				    case 'p':
   240 					len = PrintPointer(msg, maxlen,
   241 						error->args[argi++].value_ptr);
   242 					msg += len;
   243 					maxlen -= len;
   244 					break;
   245 				    case 's': /* UNICODE string */
   246 					{ Uint16 buf[ERR_MAX_STRLEN], *str;
   247 					  SDL_LookupString(error->args[argi++].buf, buf, sizeof(buf));
   248 					  str = buf;
   249 					  while ( *str && (maxlen > 0) ) {
   250 						*msg++ = *str++;
   251 						maxlen -= 1;
   252 					  }
   253 					}
   254 					break;
   255 				}
   256 				fmt += 2;
   257 			} else {
   258 				*msg++ = *fmt++;
   259 				maxlen -= 1;
   260 			}
   261 		}
   262 		*msg = 0;	/* NULL terminate the string */
   263 	}
   264 	return(errstr);
   265 }
   266 
   267 Uint8 *SDL_GetErrorMsg(Uint8 *errstr, unsigned int maxlen)
   268 {
   269 	Uint16 *errstr16;
   270 	unsigned int i;
   271 
   272 	/* Allocate the UNICODE buffer */
   273 	errstr16 = (Uint16 *)malloc(maxlen * (sizeof *errstr16));
   274 	if ( ! errstr16 ) {
   275 		strncpy((char *)errstr, "Out of memory", maxlen);
   276 		errstr[maxlen-1] = '\0';
   277 		return(errstr);
   278 	}
   279 
   280 	/* Get the error message */
   281 	SDL_GetErrorMsgUNICODE(errstr16, maxlen);
   282 
   283 	/* Convert from UNICODE to Latin1 encoding */
   284 	for ( i=0; i<maxlen; ++i ) {
   285 		errstr[i] = (Uint8)errstr16[i];
   286 	}
   287 
   288 	/* Free UNICODE buffer (if necessary) */
   289 	free(errstr16);
   290 
   291 	return(errstr);
   292 }
   293 
   294 /* Available for backwards compatibility */
   295 char *SDL_GetError (void)
   296 {
   297 	static char errmsg[SDL_ERRBUFIZE];
   298 
   299 	return((char *)SDL_GetErrorMsg((unsigned char *)errmsg, SDL_ERRBUFIZE));
   300 }
   301 
   302 void SDL_ClearError(void)
   303 {
   304 	SDL_error *error;
   305 
   306 	error = SDL_GetErrBuf();
   307 	error->error = 0;
   308 }
   309 
   310 /* Very common errors go here */
   311 void SDL_Error(SDL_errorcode code)
   312 {
   313 	switch (code) {
   314 		case SDL_ENOMEM:
   315 			SDL_SetError("Out of memory");
   316 			break;
   317 		case SDL_EFREAD:
   318 			SDL_SetError("Error reading from datastream");
   319 			break;
   320 		case SDL_EFWRITE:
   321 			SDL_SetError("Error writing to datastream");
   322 			break;
   323 		case SDL_EFSEEK:
   324 			SDL_SetError("Error seeking in datastream");
   325 			break;
   326 		default:
   327 			SDL_SetError("Unknown SDL error");
   328 			break;
   329 	}
   330 }
   331 
   332 #ifdef TEST_ERROR
   333 int main(int argc, char *argv[])
   334 {
   335 	char buffer[BUFSIZ+1];
   336 
   337 	SDL_SetError("Hi there!");
   338 	printf("Error 1: %s\n", SDL_GetError());
   339 	SDL_ClearError();
   340 	memset(buffer, '1', BUFSIZ);
   341 	buffer[BUFSIZ] = 0;
   342 	SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
   343 	printf("Error 2: %s\n", SDL_GetError());
   344 	exit(0);
   345 }
   346 #endif