diff --git a/include/SDL3/SDL_error.h b/include/SDL3/SDL_error.h index 9256ff297..fd6e652ec 100644 --- a/include/SDL3/SDL_error.h +++ b/include/SDL3/SDL_error.h @@ -82,9 +82,27 @@ extern "C" { * * \sa SDL_ClearError * \sa SDL_GetError + * \sa SDL_SetErrorV */ extern SDL_DECLSPEC bool SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); +/** + * Set the SDL error message for the current thread. + * + * Calling this function will replace any previous error message that was set. + * + * \param fmt a printf()-style message format string. + * \param ap a variable argument list. + * \returns false. + * + * \since This function is available since SDL 3.1.6. + * + * \sa SDL_ClearError + * \sa SDL_GetError + * \sa SDL_SetError + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetErrorV(SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(1); + /** * Set an error indicating that memory allocation failed. * diff --git a/src/SDL_error.c b/src/SDL_error.c index f5cb0c2c1..dca5a86c7 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -25,18 +25,29 @@ #include "SDL_error_c.h" bool SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +{ + va_list ap; + bool result; + + va_start(ap, fmt); + result = SDL_SetErrorV(fmt, ap); + va_end(ap); + return result; +} + +bool SDL_SetErrorV(SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { // Ignore call if invalid format pointer was passed if (fmt) { - va_list ap; int result; SDL_error *error = SDL_GetErrBuf(true); + va_list ap2; error->error = SDL_ErrorCodeGeneric; - va_start(ap, fmt); - result = SDL_vsnprintf(error->str, error->len, fmt, ap); - va_end(ap); + va_copy(ap2, ap); + result = SDL_vsnprintf(error->str, error->len, fmt, ap2); + va_end(ap2); if (result >= 0 && (size_t)result >= error->len && error->realloc_func) { size_t len = (size_t)result + 1; @@ -44,9 +55,9 @@ bool SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) if (str) { error->str = str; error->len = len; - va_start(ap, fmt); - (void)SDL_vsnprintf(error->str, error->len, fmt, ap); - va_end(ap); + va_copy(ap2, ap); + (void)SDL_vsnprintf(error->str, error->len, fmt, ap2); + va_end(ap2); } } diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 06cc432a9..c99ddd024 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1179,6 +1179,7 @@ SDL3_0.0.0 { SDL_StepBackUTF8; SDL_DelayPrecise; SDL_CalculateGPUTextureFormatSize; + SDL_SetErrorV; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 6de388483..444d20378 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1204,3 +1204,4 @@ #define SDL_StepBackUTF8 SDL_StepBackUTF8_REAL #define SDL_DelayPrecise SDL_DelayPrecise_REAL #define SDL_CalculateGPUTextureFormatSize SDL_CalculateGPUTextureFormatSize_REAL +#define SDL_SetErrorV SDL_SetErrorV_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index e6dcb8b80..c931a4328 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1210,3 +1210,4 @@ SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),r SDL_DYNAPI_PROC(Uint32,SDL_StepBackUTF8,(const char *a, const char **b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_DelayPrecise,(Uint64 a),(a),) SDL_DYNAPI_PROC(Uint32,SDL_CalculateGPUTextureFormatSize,(SDL_GPUTextureFormat a, Uint32 b, Uint32 c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetErrorV,(SDL_PRINTF_FORMAT_STRING const char *a,va_list b),(a,b),return)