src/SDL_error.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Feb 2014 00:53:27 -0800
changeset 8149 681eb46b8ac4
parent 8093 b43765095a6f
child 8820 0e935d5b193a
permissions -rw-r--r--
Fixed bug 2374 - Update copyright for 2014...

Is it that time already??
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "./SDL_internal.h"
    22 
    23 /* Simple error handling in SDL */
    24 
    25 #include "SDL_log.h"
    26 #include "SDL_error.h"
    27 #include "SDL_error_c.h"
    28 
    29 
    30 /* Routine to get the thread-specific error variable */
    31 #if SDL_THREADS_DISABLED
    32 /* The default (non-thread-safe) global error variable */
    33 static SDL_error SDL_global_error;
    34 #define SDL_GetErrBuf() (&SDL_global_error)
    35 #else
    36 extern SDL_error *SDL_GetErrBuf(void);
    37 #endif /* SDL_THREADS_DISABLED */
    38 
    39 #define SDL_ERRBUFIZE   1024
    40 
    41 /* Private functions */
    42 
    43 static const char *
    44 SDL_LookupString(const char *key)
    45 {
    46     /* FIXME: Add code to lookup key in language string hash-table */
    47     return key;
    48 }
    49 
    50 /* Public functions */
    51 
    52 int
    53 SDL_SetError(const char *fmt, ...)
    54 {
    55     va_list ap;
    56     SDL_error *error;
    57 
    58     /* Ignore call if invalid format pointer was passed */
    59     if (fmt == NULL) return -1;
    60 
    61     /* Copy in the key, mark error as valid */
    62     error = SDL_GetErrBuf();
    63     error->error = 1;
    64     SDL_strlcpy((char *) error->key, fmt, sizeof(error->key));
    65 
    66     va_start(ap, fmt);
    67     error->argc = 0;
    68     while (*fmt) {
    69         if (*fmt++ == '%') {
    70             while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) {
    71                 ++fmt;
    72             }
    73             switch (*fmt++) {
    74             case 0:            /* Malformed format string.. */
    75                 --fmt;
    76                 break;
    77             case 'c':
    78             case 'i':
    79             case 'd':
    80             case 'u':
    81             case 'o':
    82             case 'x':
    83             case 'X':
    84                 error->args[error->argc++].value_i = va_arg(ap, int);
    85                 break;
    86             case 'f':
    87                 error->args[error->argc++].value_f = va_arg(ap, double);
    88                 break;
    89             case 'p':
    90                 error->args[error->argc++].value_ptr = va_arg(ap, void *);
    91                 break;
    92             case 's':
    93                 {
    94                     int i = error->argc;
    95                     const char *str = va_arg(ap, const char *);
    96                     if (str == NULL)
    97                         str = "(null)";
    98                     SDL_strlcpy((char *) error->args[i].buf, str,
    99                                 ERR_MAX_STRLEN);
   100                     error->argc++;
   101                 }
   102                 break;
   103             default:
   104                 break;
   105             }
   106             if (error->argc >= ERR_MAX_ARGS) {
   107                 break;
   108             }
   109         }
   110     }
   111     va_end(ap);
   112 
   113     /* If we are in debug mode, print out an error message */
   114     SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s", SDL_GetError());
   115 
   116     return -1;
   117 }
   118 
   119 /* This function has a bit more overhead than most error functions
   120    so that it supports internationalization and thread-safe errors.
   121 */
   122 static char *
   123 SDL_GetErrorMsg(char *errstr, unsigned int maxlen)
   124 {
   125     SDL_error *error;
   126 
   127     /* Clear the error string */
   128     *errstr = '\0';
   129     --maxlen;
   130 
   131     /* Get the thread-safe error, and print it out */
   132     error = SDL_GetErrBuf();
   133     if (error->error) {
   134         const char *fmt;
   135         char *msg = errstr;
   136         int len;
   137         int argi;
   138 
   139         fmt = SDL_LookupString(error->key);
   140         argi = 0;
   141         while (*fmt && (maxlen > 0)) {
   142             if (*fmt == '%') {
   143                 char tmp[32], *spot = tmp;
   144                 *spot++ = *fmt++;
   145                 while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9'))
   146                        && spot < (tmp + SDL_arraysize(tmp) - 2)) {
   147                     *spot++ = *fmt++;
   148                 }
   149                 *spot++ = *fmt++;
   150                 *spot++ = '\0';
   151                 switch (spot[-2]) {
   152                 case '%':
   153                     *msg++ = '%';
   154                     maxlen -= 1;
   155                     break;
   156                 case 'c':
   157                 case 'i':
   158                 case 'd':
   159                 case 'u':
   160                 case 'o':
   161                 case 'x':
   162                 case 'X':
   163                     len =
   164                         SDL_snprintf(msg, maxlen, tmp,
   165                                      error->args[argi++].value_i);
   166                     msg += len;
   167                     maxlen -= len;
   168                     break;
   169                 case 'f':
   170                     len =
   171                         SDL_snprintf(msg, maxlen, tmp,
   172                                      error->args[argi++].value_f);
   173                     msg += len;
   174                     maxlen -= len;
   175                     break;
   176                 case 'p':
   177                     len =
   178                         SDL_snprintf(msg, maxlen, tmp,
   179                                      error->args[argi++].value_ptr);
   180                     msg += len;
   181                     maxlen -= len;
   182                     break;
   183                 case 's':
   184                     len =
   185                         SDL_snprintf(msg, maxlen, tmp,
   186                                      SDL_LookupString(error->args[argi++].
   187                                                       buf));
   188                     msg += len;
   189                     maxlen -= len;
   190                     break;
   191                 }
   192             } else {
   193                 *msg++ = *fmt++;
   194                 maxlen -= 1;
   195             }
   196         }
   197         *msg = 0;               /* NULL terminate the string */
   198     }
   199     return (errstr);
   200 }
   201 
   202 /* Available for backwards compatibility */
   203 const char *
   204 SDL_GetError(void)
   205 {
   206     static char errmsg[SDL_ERRBUFIZE];
   207 
   208     return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE);
   209 }
   210 
   211 void
   212 SDL_ClearError(void)
   213 {
   214     SDL_error *error;
   215 
   216     error = SDL_GetErrBuf();
   217     error->error = 0;
   218 }
   219 
   220 /* Very common errors go here */
   221 int
   222 SDL_Error(SDL_errorcode code)
   223 {
   224     switch (code) {
   225     case SDL_ENOMEM:
   226         return SDL_SetError("Out of memory");
   227     case SDL_EFREAD:
   228         return SDL_SetError("Error reading from datastream");
   229     case SDL_EFWRITE:
   230         return SDL_SetError("Error writing to datastream");
   231     case SDL_EFSEEK:
   232         return SDL_SetError("Error seeking in datastream");
   233     case SDL_UNSUPPORTED:
   234         return SDL_SetError("That operation is not supported");
   235     default:
   236         return SDL_SetError("Unknown SDL error");
   237     }
   238 }
   239 
   240 #ifdef TEST_ERROR
   241 int
   242 main(int argc, char *argv[])
   243 {
   244     char buffer[BUFSIZ + 1];
   245 
   246     SDL_SetError("Hi there!");
   247     printf("Error 1: %s\n", SDL_GetError());
   248     SDL_ClearError();
   249     SDL_memset(buffer, '1', BUFSIZ);
   250     buffer[BUFSIZ] = 0;
   251     SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
   252     printf("Error 2: %s\n", SDL_GetError());
   253     exit(0);
   254 }
   255 #endif
   256 
   257 /* vi: set ts=4 sw=4 expandtab: */