SDL_error: simplified error string management. This patch removes deferred error string formatting: now we do it during SDL_SetError(), so there's no limit on printf-style arguments used. Also removes stub for managing error string translations; we don't have the facilities to maintain that and the way we set arbitrary error strings doesn't really make this practical anyhow. Since the final error string is set right away and unique to the thread, we no longer need a static buffer for legacy SDL_GetError(), and we don't have to allocate 5x 128-byte argument fields per-thread. Also, since we now use SDL_vsnprintf instead of parsing the format string ourselves, there's a lot of code deleted and we have access to more robust formatting powers now. This does mean the final error strings can't be more than 128 bytes, down from the theoretical maximum of around 768, but I think this is probably okay. They might truncate but they will always be null-terminated! Fixes Bugzilla #5092.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
diff --git a/src/SDL_error.c b/src/SDL_error.c
index 990145b..3e5d491 100644
--- a/src/SDL_error.c
+++ b/src/SDL_error.c
@@ -27,98 +27,26 @@
#define SDL_ERRBUFIZE 1024
-/* Private functions */
-
-static const char *
-SDL_LookupString(const char *key)
-{
- /* FIXME: Add code to lookup key in language string hash-table */
- return key;
-}
-
-/* Public functions */
-
int
SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
{
- va_list ap;
- SDL_error *error;
-
/* Ignore call if invalid format pointer was passed */
- if (fmt == NULL) return -1;
+ if (fmt != NULL) {
+ va_list ap;
+ SDL_error *error = SDL_GetErrBuf();
- /* Copy in the key, mark error as valid */
- error = SDL_GetErrBuf();
- error->error = 1;
- SDL_strlcpy((char *) error->key, fmt, sizeof(error->key));
+ error->error = 1; /* mark error as valid */
- va_start(ap, fmt);
- error->argc = 0;
- while (*fmt) {
- if (*fmt++ == '%') {
- while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) {
- ++fmt;
- }
- switch (*fmt++) {
- case 0: /* Malformed format string.. */
- --fmt;
- break;
- case 'l':
- switch (*fmt++) {
- case 0: /* Malformed format string.. */
- --fmt;
- break;
- case 'i': case 'd': case 'u': case 'x': case 'X':
- error->args[error->argc++].value_l = va_arg(ap, long);
- break;
- }
- break;
- case 'c':
- case 'i':
- case 'd':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- error->args[error->argc++].value_i = va_arg(ap, int);
- break;
- case 'f':
- error->args[error->argc++].value_f = va_arg(ap, double);
- break;
- case 'p':
- error->args[error->argc++].value_ptr = va_arg(ap, void *);
- break;
- case 's':
- {
- int i = error->argc;
- const char *str = va_arg(ap, const char *);
- if (str == NULL)
- str = "(null)";
- SDL_strlcpy((char *) error->args[i].buf, str,
- ERR_MAX_STRLEN);
- error->argc++;
- }
- break;
- default:
- break;
- }
- if (error->argc >= ERR_MAX_ARGS) {
- break;
- }
+ va_start(ap, fmt);
+ SDL_vsnprintf(error->str, ERR_MAX_STRLEN, fmt, ap);
+ va_end(ap);
+
+ if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
+ /* If we are in debug mode, print out the error message */
+ SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", error->str);
}
}
- va_end(ap);
- if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
- /* If we are in debug mode, print out an error message
- * Avoid stomping on the static buffer in GetError, just
- * in case this is called while processing a ShowMessageBox to
- * show an error already in that static buffer.
- */
- char errmsg[SDL_ERRBUFIZE];
- SDL_GetErrorMsg(errmsg, sizeof(errmsg));
- SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", errmsg);
- }
return -1;
}
@@ -126,18 +54,14 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
const char *
SDL_GetError(void)
{
- static char errmsg[SDL_ERRBUFIZE];
-
- return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE);
+ const SDL_error *error = SDL_GetErrBuf();
+ return error->error ? error->str : "";
}
void
SDL_ClearError(void)
{
- SDL_error *error;
-
- error = SDL_GetErrBuf();
- error->error = 0;
+ SDL_GetErrBuf()->error = 0;
}
/* Very common errors go here */
@@ -178,129 +102,18 @@ main(int argc, char *argv[])
#endif
-/* keep this at the end of the file so it works with GCC builds that don't
- support "#pragma GCC diagnostic push" ... we'll just leave the warning
- disabled after this. */
-/* this pragma arrived in GCC 4.2 and causes a warning on older GCCs! Sigh. */
-#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 2))))
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#endif
-
-/* This function has a bit more overhead than most error functions
- so that it supports internationalization and thread-safe errors.
-*/
char *
SDL_GetErrorMsg(char *errstr, int maxlen)
{
- SDL_error *error;
-
- /* Clear the error string */
- *errstr = '\0';
- --maxlen;
+ const SDL_error *error = SDL_GetErrBuf();
- /* Get the thread-safe error, and print it out */
- error = SDL_GetErrBuf();
if (error->error) {
- const char *fmt;
- char *msg = errstr;
- int len;
- int argi;
-
- fmt = SDL_LookupString(error->key);
- argi = 0;
- while (*fmt && (maxlen > 0)) {
- if (*fmt == '%') {
- char tmp[32], *spot = tmp;
- *spot++ = *fmt++;
- while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9'))
- && spot < (tmp + SDL_arraysize(tmp) - 2)) {
- *spot++ = *fmt++;
- }
- if (*fmt == 'l') {
- *spot++ = *fmt++;
- *spot++ = *fmt++;
- *spot++ = '\0';
- switch (spot[-2]) {
- case 'i': case 'd': case 'u': case 'x': case 'X':
- len = SDL_snprintf(msg, maxlen, tmp,
- error->args[argi++].value_l);
- if (len > 0) {
- msg += len;
- maxlen -= len;
- }
- break;
- }
- continue;
- }
- *spot++ = *fmt++;
- *spot++ = '\0';
- switch (spot[-2]) {
- case '%':
- *msg++ = '%';
- maxlen -= 1;
- break;
- case 'c':
- case 'i':
- case 'd':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- len =
- SDL_snprintf(msg, maxlen, tmp,
- error->args[argi++].value_i);
- if (len > 0) {
- msg += len;
- maxlen -= len;
- }
- break;
-
- case 'f':
- len =
- SDL_snprintf(msg, maxlen, tmp,
- error->args[argi++].value_f);
- if (len > 0) {
- msg += len;
- maxlen -= len;
- }
- break;
-
- case 'p':
- len =
- SDL_snprintf(msg, maxlen, tmp,
- error->args[argi++].value_ptr);
- if (len > 0) {
- msg += len;
- maxlen -= len;
- }
- break;
-
- case 's':
- len =
- SDL_snprintf(msg, maxlen, tmp,
- SDL_LookupString(error->args[argi++].
- buf));
- if (len > 0) {
- msg += len;
- maxlen -= len;
- }
- break;
-
- }
- } else {
- *msg++ = *fmt++;
- maxlen -= 1;
- }
- }
-
- /* slide back if we've overshot the end of our buffer. */
- if (maxlen < 0) {
- msg -= (-maxlen) + 1;
- }
-
- *msg = 0; /* NULL terminate the string */
+ SDL_strlcpy(errstr, error->str, maxlen);
+ } else {
+ *errstr = '\0';
}
- return (errstr);
+
+ return errstr;
}
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/SDL_error_c.h b/src/SDL_error_c.h
index 48e3dde..88e3824 100644
--- a/src/SDL_error_c.h
+++ b/src/SDL_error_c.h
@@ -28,33 +28,11 @@
#define SDL_error_c_h_
#define ERR_MAX_STRLEN 128
-#define ERR_MAX_ARGS 5
typedef struct SDL_error
{
- /* This is a numeric value corresponding to the current error */
- int error;
-
- /* This is a key used to index into a language hashtable containing
- internationalized versions of the SDL error messages. If the key
- is not in the hashtable, or no hashtable is available, the key is
- used directly as an error message format string.
- */
- char key[ERR_MAX_STRLEN];
-
- /* These are the arguments for the error functions */
- int argc;
- union
- {
- void *value_ptr;
-#if 0 /* What is a character anyway? (UNICODE issues) */
- unsigned char value_c;
-#endif
- int value_i;
- long value_l;
- double value_f;
- char buf[ERR_MAX_STRLEN];
- } args[ERR_MAX_ARGS];
+ int error; /* This is a numeric value corresponding to the current error */
+ char str[ERR_MAX_STRLEN];
} SDL_error;
/* Defined in SDL_thread.c */