Added thread-safe environment functions

Also marked the existing functions as unsafe, as they can cause crashes if used in multi-threaded applications.

As a bonus, since the new functions are hashtable based, hint environment lookups are much faster.
This commit is contained in:
Sam Lantinga 2024-09-13 17:00:15 -07:00
parent 16ff7503b7
commit 90e01040c5
49 changed files with 696 additions and 252 deletions

View file

@ -21,13 +21,13 @@ Notes
----- -----
* gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON` * gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON`
These renderers support 720p and 1080i resolutions. These can be specified with: These renderers support 720p and 1080i resolutions. These can be specified with:
`SDL_setenv("VITA_RESOLUTION", "720", 1);` and `SDL_setenv("VITA_RESOLUTION", "1080", 1);` `SDL_SetHint(SDL_HINT_VITA_RESOLUTION, "720");` and `SDL_SetHint(SDL_HINT_VITA_RESOLUTION, "1080");`
* Desktop GL 1.X and 2.X support and renderers are also disabled by default and also can be enabled with `-DVIDEO_VITA_PVR=ON` as long as gl4es4vita is present in your SDK. * Desktop GL 1.X and 2.X support and renderers are also disabled by default and also can be enabled with `-DVIDEO_VITA_PVR=ON` as long as gl4es4vita is present in your SDK.
They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_setenv("VITA_PVR_OGL", "1", 1);` They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_SetHint(SDL_HINT_VITA_PVR_OPENGL, "1");`
anytime before video subsystem initialization. anytime before video subsystem initialization.
* gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON` * gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON`
* By default SDL emits mouse events for touch events on every touchscreen. * By default SDL emits mouse events for touch events on every touchscreen.
Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead. Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead.
Individual touchscreens can be disabled with: Individual touchscreens can be disabled with:
`SDL_setenv("VITA_DISABLE_TOUCH_FRONT", "1", 1);` and `SDL_setenv("VITA_DISABLE_TOUCH_BACK", "1", 1);` `SDL_SetHint(SDL_HINT_VITA_ENABLE_FRONT_TOUCH, "0");` and `SDL_SetHint(SDL_HINT_VITA_ENABLE_BACK_TOUCH, "0");`
* Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita. * Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita.

View file

@ -978,9 +978,213 @@ extern SDL_DECLSPEC void SDLCALL SDL_aligned_free(void *mem);
*/ */
extern SDL_DECLSPEC int SDLCALL SDL_GetNumAllocations(void); extern SDL_DECLSPEC int SDLCALL SDL_GetNumAllocations(void);
extern SDL_DECLSPEC const char * SDLCALL SDL_getenv(const char *name); /**
extern SDL_DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite); * A thread-safe set of environment variables
extern SDL_DECLSPEC int SDLCALL SDL_unsetenv(const char *name); *
* \since This struct is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CleanupEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
* \sa SDL_DestroyEnvironment
*/
typedef struct SDL_Environment SDL_Environment;
/**
* Get the process environment.
*
* This is initialized at application start and is not affected by setenv() and unsetenv() calls after that point. Use SDL_SetEnvironmentVariable() and SDL_UnsetEnvironmentVariable() if you want to modify this environment.
*
* \returns a pointer to the environment for the process or NULL on failure; call SDL_GetError()
* for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CleanupEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_GetEnvironment(void);
/**
* Cleanup the process environment.
*
* This is called during SDL_Quit() to free the process environment. If SDL_GetEnvironment() is called afterwards, it will automatically create a new environment copied from the C runtime environment.
*
* \threadsafety This function is not thread-safe.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
*/
extern SDL_DECLSPEC void SDLCALL SDL_CleanupEnvironment(void);
/**
* Create a set of environment variables
*
* \param empty SDL_TRUE to create an empty environment, SDL_FALSE to initialize it from the C runtime environment.
* \returns a pointer to the new environment or NULL on failure; call SDL_GetError()
* for more information.
*
* \threadsafety If `empty` is SDL_TRUE, it is safe to call this function from any thread, otherwise it is safe if no other threads are calling setenv() or unsetenv()
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
* \sa SDL_DestroyEnvironment
*/
extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_CreateEnvironment(SDL_bool empty);
/**
* Get the value of a variable in the environment.
*
* \param env the environment to query.
* \param name the name of the variable to get.
* \returns a pointer to the value of the variable or NULL if it can't be found.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC const char * SDLCALL SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name);
/**
* Get all variables in the environment.
*
* \param env the environment to query.
* \returns a NULL terminated array of pointers to environment variables in the form "variable=value" or NULL on
* failure; call SDL_GetError() for more information. This is a
* single allocation that should be freed with SDL_free() when it is
* no longer needed.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC char ** SDLCALL SDL_GetEnvironmentVariables(SDL_Environment *env);
/**
* Set the value of a variable in the environment.
*
* \param env the environment to modify.
* \param name the name of the variable to set.
* \param value the value of the variable to set.
* \param overwrite SDL_TRUE to overwrite the variable if it exists, SDL_FALSE to return success without setting the variable if it already exists.
* \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError()
* for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite);
/**
* Clear a variable from the environment.
*
* \param env the environment to modify.
* \param name the name of the variable to unset.
* \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError()
* for more information.
*
* \threadsafety It is safe to call this function from any thread.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironment
* \sa SDL_CreateEnvironment
* \sa SDL_GetEnvironmentVariable
* \sa SDL_GetEnvironmentVariables
* \sa SDL_SetEnvironmentVariable
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC SDL_bool SDLCALL SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name);
/**
* Destroy a set of environment variables.
*
* \param env the environment to destroy.
*
* \threadsafety It is safe to call this function from any thread, as long as the environment is no longer in use.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CreateEnvironment
*/
extern SDL_DECLSPEC void SDLCALL SDL_DestroyEnvironment(SDL_Environment *env);
/**
* Get the value of a variable in the environment.
*
* \param name the name of the variable to get.
* \returns a pointer to the value of the variable or NULL if it can't be found.
*
* \threadsafety This function is not thread safe, consider using SDL_GetEnvironmentVariable() instead.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetEnvironmentVariable
*/
extern SDL_DECLSPEC const char * SDLCALL SDL_getenv_unsafe(const char *name);
/**
* Set the value of a variable in the environment.
*
* \param name the name of the variable to set.
* \param value the value of the variable to set.
* \param overwrite 1 to overwrite the variable if it exists, 0 to return success without setting the variable if it already exists.
* \returns 0 on success, -1 on error.
*
* \threadsafety This function is not thread safe, consider using SDL_SetEnvironmentVariable() instead.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_SetEnvironmentVariable
*/
extern SDL_DECLSPEC int SDLCALL SDL_setenv_unsafe(const char *name, const char *value, int overwrite);
/**
* Clear a variable from the environment.
*
* \param name the name of the variable to unset.
* \returns 0 on success, -1 on error.
*
* \threadsafety This function is not thread safe, consider using SDL_UnsetEnvironmentVariable() instead..
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_UnsetEnvironmentVariable
*/
extern SDL_DECLSPEC int SDLCALL SDL_unsetenv_unsafe(const char *name);
typedef int (SDLCALL *SDL_CompareCallback)(const void *a, const void *b); typedef int (SDLCALL *SDL_CompareCallback)(const void *a, const void *b);
extern SDL_DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, SDL_CompareCallback compare); extern SDL_DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, SDL_CompareCallback compare);

View file

@ -255,12 +255,14 @@ void SDL_InitMainThread(void)
SDL_InitLog(); SDL_InitLog();
SDL_InitProperties(); SDL_InitProperties();
SDL_GetGlobalProperties(); SDL_GetGlobalProperties();
SDL_GetEnvironment();
SDL_InitHints(); SDL_InitHints();
} }
static void SDL_QuitMainThread(void) static void SDL_QuitMainThread(void)
{ {
SDL_QuitHints(); SDL_QuitHints();
SDL_CleanupEnvironment();
SDL_QuitProperties(); SDL_QuitProperties();
SDL_QuitLog(); SDL_QuitLog();
SDL_QuitFilesystem(); SDL_QuitFilesystem();

View file

@ -318,6 +318,11 @@ bool SDL_KeyMatchID(const void *a, const void *b, void *unused)
return false; return false;
} }
void SDL_NukeFreeKey(const void *key, const void *value, void *unused)
{
SDL_free((void *)key);
}
void SDL_NukeFreeValue(const void *key, const void *value, void *unused) void SDL_NukeFreeValue(const void *key, const void *value, void *unused)
{ {
SDL_free((void *)value); SDL_free((void *)value);

View file

@ -55,6 +55,7 @@ extern bool SDL_KeyMatchString(const void *a, const void *b, void *unused);
extern Uint32 SDL_HashID(const void *key, void *unused); extern Uint32 SDL_HashID(const void *key, void *unused);
extern bool SDL_KeyMatchID(const void *a, const void *b, void *unused); extern bool SDL_KeyMatchID(const void *a, const void *b, void *unused);
extern void SDL_NukeFreeKey(const void *key, const void *value, void *unused);
extern void SDL_NukeFreeValue(const void *key, const void *value, void *unused); extern void SDL_NukeFreeValue(const void *key, const void *value, void *unused);
#endif // SDL_hashtable_h_ #endif // SDL_hashtable_h_

View file

@ -72,7 +72,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr
return SDL_InvalidParamError("name"); return SDL_InvalidParamError("name");
} }
const char *env = SDL_getenv(name); const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
if (env && (priority < SDL_HINT_OVERRIDE)) { if (env && (priority < SDL_HINT_OVERRIDE)) {
return SDL_SetError("An environment variable is taking priority"); return SDL_SetError("An environment variable is taking priority");
} }
@ -126,7 +126,7 @@ SDL_bool SDL_ResetHint(const char *name)
return SDL_InvalidParamError("name"); return SDL_InvalidParamError("name");
} }
const char *env = SDL_getenv(name); const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
const SDL_PropertiesID hints = GetHintProperties(false); const SDL_PropertiesID hints = GetHintProperties(false);
if (!hints) { if (!hints) {
@ -165,7 +165,7 @@ static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, c
return; // uh...okay. return; // uh...okay.
} }
const char *env = SDL_getenv(name); const char *env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) { if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) {
SDL_HintWatch *entry = hint->callbacks; SDL_HintWatch *entry = hint->callbacks;
while (entry) { while (entry) {
@ -196,7 +196,7 @@ const char *SDL_GetHint(const char *name)
return NULL; return NULL;
} }
const char *result = SDL_getenv(name); const char *result = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), name);
const SDL_PropertiesID hints = GetHintProperties(false); const SDL_PropertiesID hints = GetHintProperties(false);
if (hints) { if (hints) {

View file

@ -87,7 +87,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const bool recording, const bool c
} }
// Figure out what our audio device is // Figure out what our audio device is
audiodev = SDL_getenv("AUDIODEV"); audiodev = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "AUDIODEV");
if (!audiodev) { if (!audiodev) {
if (classic) { if (classic) {
audiodev = SDL_PATH_DEV_AUDIO; audiodev = SDL_PATH_DEV_AUDIO;

View file

@ -1524,7 +1524,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
const char *utfname = (*env)->GetStringUTFChars(env, name, NULL); const char *utfname = (*env)->GetStringUTFChars(env, name, NULL);
const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL); const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL);
SDL_setenv(utfname, utfvalue, 1); // This is only called at startup, to initialize the environment
SDL_setenv_unsafe(utfname, utfvalue, 1);
(*env)->ReleaseStringUTFChars(env, name, utfname); (*env)->ReleaseStringUTFChars(env, name, utfname);
(*env)->ReleaseStringUTFChars(env, value, utfvalue); (*env)->ReleaseStringUTFChars(env, value, utfvalue);

View file

@ -331,14 +331,14 @@ static char *IBus_GetDBusAddressFilename(void)
} }
// Use this environment variable if it exists. // Use this environment variable if it exists.
addr = SDL_getenv("IBUS_ADDRESS"); addr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "IBUS_ADDRESS");
if (addr && *addr) { if (addr && *addr) {
return SDL_strdup(addr); return SDL_strdup(addr);
} }
/* Otherwise, we have to get the hostname, display, machine id, config dir /* Otherwise, we have to get the hostname, display, machine id, config dir
and look up the address from a filepath using all those bits, eek. */ and look up the address from a filepath using all those bits, eek. */
disp_env = SDL_getenv("DISPLAY"); disp_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "DISPLAY");
if (!disp_env || !*disp_env) { if (!disp_env || !*disp_env) {
display = SDL_strdup(":0.0"); display = SDL_strdup(":0.0");
@ -363,7 +363,7 @@ static char *IBus_GetDBusAddressFilename(void)
} }
if (!*host) { if (!*host) {
const char *session = SDL_getenv("XDG_SESSION_TYPE"); const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session && SDL_strcmp(session, "wayland") == 0) { if (session && SDL_strcmp(session, "wayland") == 0) {
host = "unix-wayland"; host = "unix-wayland";
} else { } else {
@ -373,11 +373,11 @@ static char *IBus_GetDBusAddressFilename(void)
SDL_memset(config_dir, 0, sizeof(config_dir)); SDL_memset(config_dir, 0, sizeof(config_dir));
conf_env = SDL_getenv("XDG_CONFIG_HOME"); conf_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CONFIG_HOME");
if (conf_env && *conf_env) { if (conf_env && *conf_env) {
SDL_strlcpy(config_dir, conf_env, sizeof(config_dir)); SDL_strlcpy(config_dir, conf_env, sizeof(config_dir));
} else { } else {
const char *home_env = SDL_getenv("HOME"); const char *home_env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home_env || !*home_env) { if (!home_env || !*home_env) {
SDL_free(display); SDL_free(display);
return NULL; return NULL;

View file

@ -44,8 +44,8 @@ static void InitIME(void)
{ {
static bool inited = false; static bool inited = false;
#ifdef HAVE_FCITX #ifdef HAVE_FCITX
const char *im_module = SDL_getenv("SDL_IM_MODULE"); const char *im_module = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_IM_MODULE");
const char *xmodifiers = SDL_getenv("XMODIFIERS"); const char *xmodifiers = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XMODIFIERS");
#endif #endif
if (inited == true) { if (inited == true) {

View file

@ -33,7 +33,9 @@ SDL_Sandbox SDL_DetectSandbox(void)
/* For Snap, we check multiple variables because they might be set for /* For Snap, we check multiple variables because they might be set for
* unrelated reasons. This is the same thing WebKitGTK does. */ * unrelated reasons. This is the same thing WebKitGTK does. */
if (SDL_getenv("SNAP") != NULL && SDL_getenv("SNAP_NAME") != NULL && SDL_getenv("SNAP_REVISION") != NULL) { if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP") != NULL &&
SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP_NAME") != NULL &&
SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SNAP_REVISION") != NULL) {
return SDL_SANDBOX_SNAP; return SDL_SANDBOX_SNAP;
} }

View file

@ -229,12 +229,12 @@ static void run_zenity(zenityArgs* arg_struct)
/* Recent versions of Zenity have different exit codes, but picks up /* Recent versions of Zenity have different exit codes, but picks up
different codes from the environment */ different codes from the environment */
SDL_setenv("ZENITY_OK", "0", 1); SDL_setenv_unsafe("ZENITY_OK", "0", 1);
SDL_setenv("ZENITY_CANCEL", "1", 1); SDL_setenv_unsafe("ZENITY_CANCEL", "1", 1);
SDL_setenv("ZENITY_ESC", "1", 1); SDL_setenv_unsafe("ZENITY_ESC", "1", 1);
SDL_setenv("ZENITY_EXTRA", "2", 1); SDL_setenv_unsafe("ZENITY_EXTRA", "2", 1);
SDL_setenv("ZENITY_ERROR", "2", 1); SDL_setenv_unsafe("ZENITY_ERROR", "2", 1);
SDL_setenv("ZENITY_TIMEOUT", "2", 1); SDL_setenv_unsafe("ZENITY_TIMEOUT", "2", 1);
execv(args[0], args); execv(args[0], args);

View file

@ -351,7 +351,7 @@ static Sint32 initialize_jumptable(Uint32 apiver, void *table, Uint32 tablesize)
// Init our jump table first. // Init our jump table first.
#if ENABLE_SDL_CALL_LOGGING #if ENABLE_SDL_CALL_LOGGING
{ {
const char *env = SDL_getenv_REAL("SDL_DYNAPI_LOG_CALLS"); const char *env = SDL_getenv_unsafe_REAL("SDL_DYNAPI_LOG_CALLS");
const SDL_bool log_calls = (env && SDL_atoi_REAL(env)); const SDL_bool log_calls = (env && SDL_atoi_REAL(env));
if (log_calls) { if (log_calls) {
#define SDL_DYNAPI_PROC(rc, fn, params, args, ret) jump_table.fn = fn##_LOGSDLCALLS; #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) jump_table.fn = fn##_LOGSDLCALLS;
@ -461,7 +461,7 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
static void SDL_InitDynamicAPILocked(void) static void SDL_InitDynamicAPILocked(void)
{ {
const char *libname = SDL_getenv_REAL(SDL_DYNAMIC_API_ENVVAR); const char *libname = SDL_getenv_unsafe_REAL(SDL_DYNAMIC_API_ENVVAR);
SDL_DYNAPI_ENTRYFN entry = NULL; // funcs from here by default. SDL_DYNAPI_ENTRYFN entry = NULL; // funcs from here by default.
SDL_bool use_internal = SDL_TRUE; SDL_bool use_internal = SDL_TRUE;

View file

@ -52,6 +52,7 @@ SDL3_0.0.0 {
SDL_BroadcastCondition; SDL_BroadcastCondition;
SDL_CaptureMouse; SDL_CaptureMouse;
SDL_ClaimWindowForGPUDevice; SDL_ClaimWindowForGPUDevice;
SDL_CleanupEnvironment;
SDL_CleanupTLS; SDL_CleanupTLS;
SDL_ClearAudioStream; SDL_ClearAudioStream;
SDL_ClearClipboardData; SDL_ClearClipboardData;
@ -84,6 +85,7 @@ SDL3_0.0.0 {
SDL_CreateCondition; SDL_CreateCondition;
SDL_CreateCursor; SDL_CreateCursor;
SDL_CreateDirectory; SDL_CreateDirectory;
SDL_CreateEnvironment;
SDL_CreateGPUBuffer; SDL_CreateGPUBuffer;
SDL_CreateGPUComputePipeline; SDL_CreateGPUComputePipeline;
SDL_CreateGPUDevice; SDL_CreateGPUDevice;
@ -125,6 +127,7 @@ SDL3_0.0.0 {
SDL_DestroyAudioStream; SDL_DestroyAudioStream;
SDL_DestroyCondition; SDL_DestroyCondition;
SDL_DestroyCursor; SDL_DestroyCursor;
SDL_DestroyEnvironment;
SDL_DestroyGPUDevice; SDL_DestroyGPUDevice;
SDL_DestroyHapticEffect; SDL_DestroyHapticEffect;
SDL_DestroyMutex; SDL_DestroyMutex;
@ -276,6 +279,9 @@ SDL3_0.0.0 {
SDL_GetDisplayProperties; SDL_GetDisplayProperties;
SDL_GetDisplayUsableBounds; SDL_GetDisplayUsableBounds;
SDL_GetDisplays; SDL_GetDisplays;
SDL_GetEnvironment;
SDL_GetEnvironmentVariable;
SDL_GetEnvironmentVariables;
SDL_GetError; SDL_GetError;
SDL_GetEventFilter; SDL_GetEventFilter;
SDL_GetFloatProperty; SDL_GetFloatProperty;
@ -785,6 +791,7 @@ SDL3_0.0.0 {
SDL_SetClipboardData; SDL_SetClipboardData;
SDL_SetClipboardText; SDL_SetClipboardText;
SDL_SetCursor; SDL_SetCursor;
SDL_SetEnvironmentVariable;
SDL_SetError; SDL_SetError;
SDL_SetEventEnabled; SDL_SetEventEnabled;
SDL_SetEventFilter; SDL_SetEventFilter;
@ -933,6 +940,7 @@ SDL3_0.0.0 {
SDL_UnlockTexture; SDL_UnlockTexture;
SDL_UnmapGPUTransferBuffer; SDL_UnmapGPUTransferBuffer;
SDL_UnregisterApp; SDL_UnregisterApp;
SDL_UnsetEnvironmentVariable;
SDL_UpdateGamepads; SDL_UpdateGamepads;
SDL_UpdateHapticEffect; SDL_UpdateHapticEffect;
SDL_UpdateJoysticks; SDL_UpdateJoysticks;
@ -1020,7 +1028,7 @@ SDL3_0.0.0 {
SDL_fmod; SDL_fmod;
SDL_fmodf; SDL_fmodf;
SDL_free; SDL_free;
SDL_getenv; SDL_getenv_unsafe;
SDL_hid_ble_scan; SDL_hid_ble_scan;
SDL_hid_close; SDL_hid_close;
SDL_hid_device_change_count; SDL_hid_device_change_count;
@ -1095,7 +1103,7 @@ SDL3_0.0.0 {
SDL_roundf; SDL_roundf;
SDL_scalbn; SDL_scalbn;
SDL_scalbnf; SDL_scalbnf;
SDL_setenv; SDL_setenv_unsafe;
SDL_sin; SDL_sin;
SDL_sinf; SDL_sinf;
SDL_snprintf; SDL_snprintf;
@ -1138,7 +1146,7 @@ SDL3_0.0.0 {
SDL_uitoa; SDL_uitoa;
SDL_ulltoa; SDL_ulltoa;
SDL_ultoa; SDL_ultoa;
SDL_unsetenv; SDL_unsetenv_unsafe;
SDL_utf8strlcpy; SDL_utf8strlcpy;
SDL_utf8strlen; SDL_utf8strlen;
SDL_utf8strnlen; SDL_utf8strnlen;

View file

@ -77,6 +77,7 @@
#define SDL_BroadcastCondition SDL_BroadcastCondition_REAL #define SDL_BroadcastCondition SDL_BroadcastCondition_REAL
#define SDL_CaptureMouse SDL_CaptureMouse_REAL #define SDL_CaptureMouse SDL_CaptureMouse_REAL
#define SDL_ClaimWindowForGPUDevice SDL_ClaimWindowForGPUDevice_REAL #define SDL_ClaimWindowForGPUDevice SDL_ClaimWindowForGPUDevice_REAL
#define SDL_CleanupEnvironment SDL_CleanupEnvironment_REAL
#define SDL_CleanupTLS SDL_CleanupTLS_REAL #define SDL_CleanupTLS SDL_CleanupTLS_REAL
#define SDL_ClearAudioStream SDL_ClearAudioStream_REAL #define SDL_ClearAudioStream SDL_ClearAudioStream_REAL
#define SDL_ClearClipboardData SDL_ClearClipboardData_REAL #define SDL_ClearClipboardData SDL_ClearClipboardData_REAL
@ -109,6 +110,7 @@
#define SDL_CreateCondition SDL_CreateCondition_REAL #define SDL_CreateCondition SDL_CreateCondition_REAL
#define SDL_CreateCursor SDL_CreateCursor_REAL #define SDL_CreateCursor SDL_CreateCursor_REAL
#define SDL_CreateDirectory SDL_CreateDirectory_REAL #define SDL_CreateDirectory SDL_CreateDirectory_REAL
#define SDL_CreateEnvironment SDL_CreateEnvironment_REAL
#define SDL_CreateGPUBuffer SDL_CreateGPUBuffer_REAL #define SDL_CreateGPUBuffer SDL_CreateGPUBuffer_REAL
#define SDL_CreateGPUComputePipeline SDL_CreateGPUComputePipeline_REAL #define SDL_CreateGPUComputePipeline SDL_CreateGPUComputePipeline_REAL
#define SDL_CreateGPUDevice SDL_CreateGPUDevice_REAL #define SDL_CreateGPUDevice SDL_CreateGPUDevice_REAL
@ -150,6 +152,7 @@
#define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL #define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL
#define SDL_DestroyCondition SDL_DestroyCondition_REAL #define SDL_DestroyCondition SDL_DestroyCondition_REAL
#define SDL_DestroyCursor SDL_DestroyCursor_REAL #define SDL_DestroyCursor SDL_DestroyCursor_REAL
#define SDL_DestroyEnvironment SDL_DestroyEnvironment_REAL
#define SDL_DestroyGPUDevice SDL_DestroyGPUDevice_REAL #define SDL_DestroyGPUDevice SDL_DestroyGPUDevice_REAL
#define SDL_DestroyHapticEffect SDL_DestroyHapticEffect_REAL #define SDL_DestroyHapticEffect SDL_DestroyHapticEffect_REAL
#define SDL_DestroyMutex SDL_DestroyMutex_REAL #define SDL_DestroyMutex SDL_DestroyMutex_REAL
@ -301,6 +304,9 @@
#define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL
#define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL #define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL
#define SDL_GetDisplays SDL_GetDisplays_REAL #define SDL_GetDisplays SDL_GetDisplays_REAL
#define SDL_GetEnvironment SDL_GetEnvironment_REAL
#define SDL_GetEnvironmentVariable SDL_GetEnvironmentVariable_REAL
#define SDL_GetEnvironmentVariables SDL_GetEnvironmentVariables_REAL
#define SDL_GetError SDL_GetError_REAL #define SDL_GetError SDL_GetError_REAL
#define SDL_GetEventFilter SDL_GetEventFilter_REAL #define SDL_GetEventFilter SDL_GetEventFilter_REAL
#define SDL_GetFloatProperty SDL_GetFloatProperty_REAL #define SDL_GetFloatProperty SDL_GetFloatProperty_REAL
@ -810,6 +816,7 @@
#define SDL_SetClipboardData SDL_SetClipboardData_REAL #define SDL_SetClipboardData SDL_SetClipboardData_REAL
#define SDL_SetClipboardText SDL_SetClipboardText_REAL #define SDL_SetClipboardText SDL_SetClipboardText_REAL
#define SDL_SetCursor SDL_SetCursor_REAL #define SDL_SetCursor SDL_SetCursor_REAL
#define SDL_SetEnvironmentVariable SDL_SetEnvironmentVariable_REAL
#define SDL_SetError SDL_SetError_REAL #define SDL_SetError SDL_SetError_REAL
#define SDL_SetEventEnabled SDL_SetEventEnabled_REAL #define SDL_SetEventEnabled SDL_SetEventEnabled_REAL
#define SDL_SetEventFilter SDL_SetEventFilter_REAL #define SDL_SetEventFilter SDL_SetEventFilter_REAL
@ -958,6 +965,7 @@
#define SDL_UnlockTexture SDL_UnlockTexture_REAL #define SDL_UnlockTexture SDL_UnlockTexture_REAL
#define SDL_UnmapGPUTransferBuffer SDL_UnmapGPUTransferBuffer_REAL #define SDL_UnmapGPUTransferBuffer SDL_UnmapGPUTransferBuffer_REAL
#define SDL_UnregisterApp SDL_UnregisterApp_REAL #define SDL_UnregisterApp SDL_UnregisterApp_REAL
#define SDL_UnsetEnvironmentVariable SDL_UnsetEnvironmentVariable_REAL
#define SDL_UpdateGamepads SDL_UpdateGamepads_REAL #define SDL_UpdateGamepads SDL_UpdateGamepads_REAL
#define SDL_UpdateHapticEffect SDL_UpdateHapticEffect_REAL #define SDL_UpdateHapticEffect SDL_UpdateHapticEffect_REAL
#define SDL_UpdateJoysticks SDL_UpdateJoysticks_REAL #define SDL_UpdateJoysticks SDL_UpdateJoysticks_REAL
@ -1045,7 +1053,7 @@
#define SDL_fmod SDL_fmod_REAL #define SDL_fmod SDL_fmod_REAL
#define SDL_fmodf SDL_fmodf_REAL #define SDL_fmodf SDL_fmodf_REAL
#define SDL_free SDL_free_REAL #define SDL_free SDL_free_REAL
#define SDL_getenv SDL_getenv_REAL #define SDL_getenv_unsafe SDL_getenv_unsafe_REAL
#define SDL_hid_ble_scan SDL_hid_ble_scan_REAL #define SDL_hid_ble_scan SDL_hid_ble_scan_REAL
#define SDL_hid_close SDL_hid_close_REAL #define SDL_hid_close SDL_hid_close_REAL
#define SDL_hid_device_change_count SDL_hid_device_change_count_REAL #define SDL_hid_device_change_count SDL_hid_device_change_count_REAL
@ -1120,7 +1128,7 @@
#define SDL_roundf SDL_roundf_REAL #define SDL_roundf SDL_roundf_REAL
#define SDL_scalbn SDL_scalbn_REAL #define SDL_scalbn SDL_scalbn_REAL
#define SDL_scalbnf SDL_scalbnf_REAL #define SDL_scalbnf SDL_scalbnf_REAL
#define SDL_setenv SDL_setenv_REAL #define SDL_setenv_unsafe SDL_setenv_unsafe_REAL
#define SDL_sin SDL_sin_REAL #define SDL_sin SDL_sin_REAL
#define SDL_sinf SDL_sinf_REAL #define SDL_sinf SDL_sinf_REAL
#define SDL_snprintf SDL_snprintf_REAL #define SDL_snprintf SDL_snprintf_REAL
@ -1163,7 +1171,7 @@
#define SDL_uitoa SDL_uitoa_REAL #define SDL_uitoa SDL_uitoa_REAL
#define SDL_ulltoa SDL_ulltoa_REAL #define SDL_ulltoa SDL_ulltoa_REAL
#define SDL_ultoa SDL_ultoa_REAL #define SDL_ultoa SDL_ultoa_REAL
#define SDL_unsetenv SDL_unsetenv_REAL #define SDL_unsetenv_unsafe SDL_unsetenv_unsafe_REAL
#define SDL_utf8strlcpy SDL_utf8strlcpy_REAL #define SDL_utf8strlcpy SDL_utf8strlcpy_REAL
#define SDL_utf8strlen SDL_utf8strlen_REAL #define SDL_utf8strlen SDL_utf8strlen_REAL
#define SDL_utf8strnlen SDL_utf8strnlen_REAL #define SDL_utf8strnlen SDL_utf8strnlen_REAL

View file

@ -97,6 +97,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const S
SDL_DYNAPI_PROC(void,SDL_BroadcastCondition,(SDL_Condition *a),(a),) SDL_DYNAPI_PROC(void,SDL_BroadcastCondition,(SDL_Condition *a),(a),)
SDL_DYNAPI_PROC(SDL_bool,SDL_CaptureMouse,(SDL_bool a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_CaptureMouse,(SDL_bool a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_ClaimWindowForGPUDevice,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_ClaimWindowForGPUDevice,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_CleanupEnvironment,(void),(),)
SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),) SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_ClearClipboardData,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_ClearClipboardData,(void),(),return)
@ -129,6 +130,7 @@ SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateColorCursor,(SDL_Surface *a, int b, int c)
SDL_DYNAPI_PROC(SDL_Condition*,SDL_CreateCondition,(void),(),return) SDL_DYNAPI_PROC(SDL_Condition*,SDL_CreateCondition,(void),(),return)
SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateCursor,(const Uint8 *a, const Uint8 *b, int c, int d, int e, int f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateCursor,(const Uint8 *a, const Uint8 *b, int c, int d, int e, int f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_CreateDirectory,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_CreateDirectory,(const char *a),(a),return)
SDL_DYNAPI_PROC(SDL_Environment*,SDL_CreateEnvironment,(SDL_bool a),(a),return)
SDL_DYNAPI_PROC(SDL_GPUBuffer*,SDL_CreateGPUBuffer,(SDL_GPUDevice *a, const SDL_GPUBufferCreateInfo* b),(a,b),return) SDL_DYNAPI_PROC(SDL_GPUBuffer*,SDL_CreateGPUBuffer,(SDL_GPUDevice *a, const SDL_GPUBufferCreateInfo* b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GPUComputePipeline*,SDL_CreateGPUComputePipeline,(SDL_GPUDevice *a, const SDL_GPUComputePipelineCreateInfo *b),(a,b),return) SDL_DYNAPI_PROC(SDL_GPUComputePipeline*,SDL_CreateGPUComputePipeline,(SDL_GPUDevice *a, const SDL_GPUComputePipelineCreateInfo *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_CreateGPUDevice,(SDL_GPUShaderFormat a, SDL_bool b, const char *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_CreateGPUDevice,(SDL_GPUShaderFormat a, SDL_bool b, const char *c),(a,b,c),return)
@ -170,6 +172,7 @@ SDL_DYNAPI_PROC(void,SDL_DelayNS,(Uint64 a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyCondition,(SDL_Condition *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyCondition,(SDL_Condition *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyCursor,(SDL_Cursor *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyCursor,(SDL_Cursor *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyEnvironment,(SDL_Environment *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyGPUDevice,(SDL_GPUDevice *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyGPUDevice,(SDL_GPUDevice *a),(a),)
SDL_DYNAPI_PROC(void,SDL_DestroyHapticEffect,(SDL_Haptic *a, int b),(a,b),) SDL_DYNAPI_PROC(void,SDL_DestroyHapticEffect,(SDL_Haptic *a, int b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_DestroyMutex,(SDL_Mutex *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyMutex,(SDL_Mutex *a),(a),)
@ -321,6 +324,9 @@ SDL_DYNAPI_PROC(const char*,SDL_GetDisplayName,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return)
SDL_DYNAPI_PROC(SDL_Environment*,SDL_GetEnvironment,(void),(),return)
SDL_DYNAPI_PROC(const char*,SDL_GetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(char**,SDL_GetEnvironmentVariables,(SDL_Environment *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
@ -821,6 +827,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char
SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, SDL_ClipboardCleanupCallback b, void *c, const char **d, size_t e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, SDL_ClipboardCleanupCallback b, void *c, const char **d, size_t e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardText,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_SetClipboardText,(const char *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetCursor,(SDL_Cursor *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_SetCursor,(SDL_Cursor *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetEnvironmentVariable,(SDL_Environment *a, const char *b, const char *c, SDL_bool d),(a,b,c,d),return)
SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, SDL_bool b),(a,b),) SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, SDL_bool b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),)
SDL_DYNAPI_PROC(SDL_bool,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_bool,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
@ -968,6 +975,7 @@ SDL_DYNAPI_PROC(void,SDL_UnlockSurface,(SDL_Surface *a),(a),)
SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),)
SDL_DYNAPI_PROC(void,SDL_UnmapGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_UnmapGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_UnsetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),) SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_UpdateHapticEffect,(SDL_Haptic *a, int b, const SDL_HapticEffect *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_bool,SDL_UpdateHapticEffect,(SDL_Haptic *a, int b, const SDL_HapticEffect *c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_UpdateJoysticks,(void),(),) SDL_DYNAPI_PROC(void,SDL_UpdateJoysticks,(void),(),)
@ -1054,7 +1062,7 @@ SDL_DYNAPI_PROC(float,SDL_floorf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_fmod,(double a, double b),(a,b),return) SDL_DYNAPI_PROC(double,SDL_fmod,(double a, double b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_fmodf,(float a, float b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_fmodf,(float a, float b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_free,(void *a),(a),) SDL_DYNAPI_PROC(void,SDL_free,(void *a),(a),)
SDL_DYNAPI_PROC(const char*,SDL_getenv,(const char *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_getenv_unsafe,(const char *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_hid_ble_scan,(SDL_bool a),(a),) SDL_DYNAPI_PROC(void,SDL_hid_ble_scan,(SDL_bool a),(a),)
SDL_DYNAPI_PROC(int,SDL_hid_close,(SDL_hid_device *a),(a),return) SDL_DYNAPI_PROC(int,SDL_hid_close,(SDL_hid_device *a),(a),return)
SDL_DYNAPI_PROC(Uint32,SDL_hid_device_change_count,(void),(),return) SDL_DYNAPI_PROC(Uint32,SDL_hid_device_change_count,(void),(),return)
@ -1129,7 +1137,7 @@ SDL_DYNAPI_PROC(double,SDL_round,(double a),(a),return)
SDL_DYNAPI_PROC(float,SDL_roundf,(float a),(a),return) SDL_DYNAPI_PROC(float,SDL_roundf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_scalbn,(double a, int b),(a,b),return) SDL_DYNAPI_PROC(double,SDL_scalbn,(double a, int b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_scalbnf,(float a, int b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_scalbnf,(float a, int b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_setenv,(const char *a, const char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_setenv_unsafe,(const char *a, const char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(double,SDL_sin,(double a),(a),return) SDL_DYNAPI_PROC(double,SDL_sin,(double a),(a),return)
SDL_DYNAPI_PROC(float,SDL_sinf,(float a),(a),return) SDL_DYNAPI_PROC(float,SDL_sinf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_sqrt,(double a),(a),return) SDL_DYNAPI_PROC(double,SDL_sqrt,(double a),(a),return)
@ -1169,7 +1177,7 @@ SDL_DYNAPI_PROC(float,SDL_truncf,(float a),(a),return)
SDL_DYNAPI_PROC(char*,SDL_uitoa,(unsigned int a, char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(char*,SDL_uitoa,(unsigned int a, char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(char*,SDL_ulltoa,(unsigned long long a, char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(char*,SDL_ulltoa,(unsigned long long a, char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(char*,SDL_ultoa,(unsigned long a, char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(char*,SDL_ultoa,(unsigned long a, char *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_unsetenv,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_unsetenv_unsafe,(const char *a),(a),return)
SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return)
SDL_DYNAPI_PROC(size_t,SDL_utf8strnlen,(const char *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strnlen,(const char *a, size_t b),(a,b),return)

View file

@ -144,7 +144,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
switch (folder) { switch (folder) {
case SDL_FOLDER_HOME: case SDL_FOLDER_HOME:
base = SDL_getenv("HOME"); base = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!base) { if (!base) {
SDL_SetError("No $HOME environment variable available"); SDL_SetError("No $HOME environment variable available");

View file

@ -93,7 +93,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
return NULL; return NULL;
} }
home = SDL_getenv("HOME"); home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home) { if (!home) {
SDL_SetError("No $HOME environment variable available"); SDL_SetError("No $HOME environment variable available");
return NULL; return NULL;

View file

@ -68,7 +68,7 @@ char *SDL_SYS_GetBasePath(void)
char *SDL_SYS_GetPrefPath(const char *org, const char *app) char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{ {
// !!! FIXME: is there a better way to do this? // !!! FIXME: is there a better way to do this?
const char *home = SDL_getenv("HOME"); const char *home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
const char *append = "/config/settings/"; const char *append = "/config/settings/";
size_t len = SDL_strlen(home); size_t len = SDL_strlen(home);
@ -102,7 +102,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
const char *home = NULL; const char *home = NULL;
char *result; char *result;
home = SDL_getenv("HOME"); home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home) { if (!home) {
SDL_SetError("No $HOME environment variable available"); SDL_SetError("No $HOME environment variable available");
return NULL; return NULL;

View file

@ -74,7 +74,7 @@ static char *readSymLink(const char *path)
#ifdef SDL_PLATFORM_OPENBSD #ifdef SDL_PLATFORM_OPENBSD
static char *search_path_for_binary(const char *bin) static char *search_path_for_binary(const char *bin)
{ {
const char *envr_real = SDL_getenv("PATH"); const char *envr_real = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PATH");
char *envr; char *envr;
size_t alloc_size; size_t alloc_size;
char *exe = NULL; char *exe = NULL;
@ -163,7 +163,7 @@ char *SDL_SYS_GetBasePath(void)
exe = search_path_for_binary(cmdline[0]); exe = search_path_for_binary(cmdline[0]);
} else { } else {
if (exe && *exe == '.') { if (exe && *exe == '.') {
const char *pwd = SDL_getenv("PWD"); const char *pwd = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "PWD");
if (pwd && *pwd) { if (pwd && *pwd) {
SDL_asprintf(&pwddst, "%s/%s", pwd, exe); SDL_asprintf(&pwddst, "%s/%s", pwd, exe);
} }
@ -265,7 +265,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
* *
* http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
*/ */
const char *envr = SDL_getenv("XDG_DATA_HOME"); const char *envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_DATA_HOME");
const char *append; const char *append;
char *result = NULL; char *result = NULL;
char *ptr = NULL; char *ptr = NULL;
@ -281,7 +281,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
if (!envr) { if (!envr) {
// You end up with "$HOME/.local/share/Game Name 2" // You end up with "$HOME/.local/share/Game Name 2"
envr = SDL_getenv("HOME"); envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!envr) { if (!envr) {
// we could take heroic measures with /etc/passwd, but oh well. // we could take heroic measures with /etc/passwd, but oh well.
SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set"); SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set");
@ -368,12 +368,12 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa
int relative; int relative;
size_t l; size_t l;
home_dir = SDL_getenv ("HOME"); home_dir = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home_dir) if (!home_dir)
goto error; goto error;
config_home = SDL_getenv ("XDG_CONFIG_HOME"); config_home = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CONFIG_HOME");
if (!config_home || config_home[0] == 0) if (!config_home || config_home[0] == 0)
{ {
l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1; l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1;
@ -495,7 +495,7 @@ static char *xdg_user_dir_lookup (const char *type)
if (dir) if (dir)
return dir; return dir;
home_dir = SDL_getenv("HOME"); home_dir = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!home_dir) if (!home_dir)
return NULL; return NULL;
@ -533,7 +533,7 @@ char *SDL_SYS_GetUserFolder(SDL_Folder folder)
*/ */
switch(folder) { switch(folder) {
case SDL_FOLDER_HOME: case SDL_FOLDER_HOME:
param = SDL_getenv("HOME"); param = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "HOME");
if (!param) { if (!param) {
SDL_SetError("No $HOME environment variable available"); SDL_SetError("No $HOME environment variable available");

View file

@ -11591,7 +11591,7 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
static void VULKAN_INTERNAL_LoadEntryPoints(void) static void VULKAN_INTERNAL_LoadEntryPoints(void)
{ {
// Required for MoltenVK support // Required for MoltenVK support
SDL_setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); SDL_setenv_unsafe("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
// Load Vulkan entry points // Load Vulkan entry points
if (!SDL_Vulkan_LoadLibrary(NULL)) { if (!SDL_Vulkan_LoadLibrary(NULL)) {

View file

@ -537,7 +537,7 @@ SDL_bool SDL_SetHapticGain(SDL_Haptic *haptic, int gain)
} }
// The user can use an environment variable to override the max gain. // The user can use an environment variable to override the max gain.
env = SDL_getenv("SDL_HAPTIC_GAIN_MAX"); env = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_HAPTIC_GAIN_MAX");
if (env) { if (env) {
max_gain = SDL_atoi(env); max_gain = SDL_atoi(env);

View file

@ -78,13 +78,13 @@ bool SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
*tmp = '\0'; *tmp = '\0';
// LANG is the primary locale (maybe) // LANG is the primary locale (maybe)
envr = SDL_getenv("LANG"); envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG");
if (envr) { if (envr) {
SDL_strlcpy(tmp, envr, buflen); SDL_strlcpy(tmp, envr, buflen);
} }
// fallback languages // fallback languages
envr = SDL_getenv("LANGUAGE"); envr = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANGUAGE");
if (envr) { if (envr) {
if (*tmp) { if (*tmp) {
SDL_strlcat(tmp, ":", buflen); SDL_strlcat(tmp, ":", buflen);

View file

@ -48,7 +48,7 @@ int SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserv
_free(cvalue); _free(cvalue);
} }
} }
}, SDL_setenv); }, SDL_setenv_unsafe);
return mainFunction(argc, argv); return mainFunction(argc, argv);
} }

View file

@ -41,7 +41,7 @@ bool SDL_SYS_OpenURL(const char *url)
pid_t pid2; pid_t pid2;
const char *args[] = { "xdg-open", url, NULL }; const char *args[] = { "xdg-open", url, NULL };
// Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam // Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam
SDL_unsetenv("LD_PRELOAD"); SDL_unsetenv_unsafe("LD_PRELOAD");
if (posix_spawnp(&pid2, args[0], NULL, NULL, (char **)args, environ) == 0) { if (posix_spawnp(&pid2, args[0], NULL, NULL, (char **)args, environ) == 0) {
// Child process doesn't wait for possibly-blocking grandchild. // Child process doesn't wait for possibly-blocking grandchild.
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
@ -51,7 +51,7 @@ bool SDL_SYS_OpenURL(const char *url)
#else #else
pid_t pid2; pid_t pid2;
// Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam // Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam
SDL_unsetenv("LD_PRELOAD"); SDL_unsetenv_unsafe("LD_PRELOAD");
// Notice this is vfork and not fork! // Notice this is vfork and not fork!
pid2 = vfork(); pid2 = vfork();
if (pid2 == 0) { // Grandchild process will try to launch the url if (pid2 == 0) { // Grandchild process will try to launch the url

View file

@ -35,15 +35,6 @@
#include "../SDL_sysprocess.h" #include "../SDL_sysprocess.h"
#include "../../file/SDL_iostream_c.h" #include "../../file/SDL_iostream_c.h"
#if defined(SDL_PLATFORM_MACOS)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
#else
extern char **environ;
#endif
#define READ_END 0 #define READ_END 0
#define WRITE_END 1 #define WRITE_END 1
@ -114,7 +105,7 @@ static bool GetStreamFD(SDL_PropertiesID props, const char *property, int *resul
bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID props) bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID props)
{ {
char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL); char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL);
char * const *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, environ); char * const *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, NULL);
SDL_ProcessIO stdin_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL); SDL_ProcessIO stdin_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
SDL_ProcessIO stdout_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_INHERITED); SDL_ProcessIO stdout_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_INHERITED);
SDL_ProcessIO stderr_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_INHERITED); SDL_ProcessIO stderr_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_INHERITED);
@ -124,6 +115,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
int stdout_pipe[2] = { -1, -1 }; int stdout_pipe[2] = { -1, -1 };
int stderr_pipe[2] = { -1, -1 }; int stderr_pipe[2] = { -1, -1 };
int fd = -1; int fd = -1;
char **env_copy = NULL;
// Keep the malloc() before exec() so that an OOM won't run a process at all // Keep the malloc() before exec() so that an OOM won't run a process at all
SDL_ProcessData *data = SDL_calloc(1, sizeof(*data)); SDL_ProcessData *data = SDL_calloc(1, sizeof(*data));
@ -278,6 +270,11 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
} }
} }
if (!env) {
env_copy = SDL_GetEnvironmentVariables(SDL_GetEnvironment());
env = env_copy;
}
// Spawn the new process // Spawn the new process
if (posix_spawnp(&data->pid, args[0], &fa, &attr, args, env) != 0) { if (posix_spawnp(&data->pid, args[0], &fa, &attr, args, env) != 0) {
SDL_SetError("posix_spawn failed: %s", strerror(errno)); SDL_SetError("posix_spawn failed: %s", strerror(errno));
@ -308,6 +305,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
posix_spawn_file_actions_destroy(&fa); posix_spawn_file_actions_destroy(&fa);
posix_spawnattr_destroy(&attr); posix_spawnattr_destroy(&attr);
SDL_free(env_copy);
return true; return true;
@ -338,6 +336,7 @@ posix_spawn_fail_none:
if (stderr_pipe[WRITE_END] >= 0) { if (stderr_pipe[WRITE_END] >= 0) {
close(stderr_pipe[WRITE_END]); close(stderr_pipe[WRITE_END]);
} }
SDL_free(env_copy);
return false; return false;
} }

View file

@ -186,6 +186,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
HANDLE stdin_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; HANDLE stdin_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
HANDLE stdout_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; HANDLE stdout_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
HANDLE stderr_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; HANDLE stderr_pipe[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
char **env_copy = NULL;
bool result = false; bool result = false;
// Keep the malloc() before exec() so that an OOM won't run a process at all // Keep the malloc() before exec() so that an OOM won't run a process at all
@ -199,6 +200,10 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
goto done; goto done;
} }
if (!env) {
env_copy = SDL_GetEnvironmentVariables(SDL_GetEnvironment());
env = (const char * const *)env_copy;
}
if (!join_env(env, &createprocess_env)) { if (!join_env(env, &createprocess_env)) {
goto done; goto done;
} }
@ -381,6 +386,7 @@ done:
} }
SDL_free(createprocess_cmdline); SDL_free(createprocess_cmdline);
SDL_free(createprocess_env); SDL_free(createprocess_env);
SDL_free(env_copy);
if (!result) { if (!result) {
if (stdin_pipe[WRITE_END] != INVALID_HANDLE_VALUE) { if (stdin_pipe[WRITE_END] != INVALID_HANDLE_VALUE) {

View file

@ -21,6 +21,7 @@
#include "SDL_internal.h" #include "SDL_internal.h"
#include "SDL_getenv_c.h" #include "SDL_getenv_c.h"
#include "../SDL_hashtable.h"
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
#include "../core/windows/SDL_windows.h" #include "../core/windows/SDL_windows.h"
@ -40,11 +41,23 @@
#define HAVE_LOCAL_ENVIRONMENT #define HAVE_LOCAL_ENVIRONMENT
#endif #endif
#if !defined(SDL_PLATFORM_WINDOWS)
#if defined(SDL_PLATFORM_MACOS)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
#else
extern char **environ;
#endif
#endif // !SDL_PLATFORM_WINDOWS
// Put a variable into the environment // Put a variable into the environment
// Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/) // Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/)
#ifdef HAVE_LIBC_ENVIRONMENT #ifdef HAVE_LIBC_ENVIRONMENT
#if defined(HAVE_SETENV) #if defined(HAVE_SETENV)
int SDL_setenv(const char *name, const char *value, int overwrite) int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{ {
// Input validation // Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
@ -55,7 +68,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
} }
// We have a real environment table, but no real setenv? Fake it w/ putenv. // We have a real environment table, but no real setenv? Fake it w/ putenv.
#else #else
int SDL_setenv(const char *name, const char *value, int overwrite) int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{ {
char *new_variable; char *new_variable;
@ -79,7 +92,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
} }
#endif #endif
#elif defined(HAVE_WIN32_ENVIRONMENT) #elif defined(HAVE_WIN32_ENVIRONMENT)
int SDL_setenv(const char *name, const char *value, int overwrite) int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{ {
// Input validation // Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) { if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
@ -101,7 +114,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
// We'll leak this, as environment variables are intended to persist past SDL_Quit() // We'll leak this, as environment variables are intended to persist past SDL_Quit()
static char **SDL_env; static char **SDL_env;
int SDL_setenv(const char *name, const char *value, int overwrite) int SDL_setenv_unsafe(const char *name, const char *value, int overwrite)
{ {
int added; int added;
size_t len, i; size_t len, i;
@ -114,7 +127,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
} }
// See if it already exists // See if it already exists
if (!overwrite && SDL_getenv(name)) { if (!overwrite && SDL_getenv_unsafe(name)) {
return 0; return 0;
} }
@ -164,7 +177,7 @@ int SDL_setenv(const char *name, const char *value, int overwrite)
#ifdef HAVE_LIBC_ENVIRONMENT #ifdef HAVE_LIBC_ENVIRONMENT
#if defined(HAVE_UNSETENV) #if defined(HAVE_UNSETENV)
int SDL_unsetenv(const char *name) int SDL_unsetenv_unsafe(const char *name)
{ {
// Input validation // Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
@ -175,7 +188,7 @@ int SDL_unsetenv(const char *name)
} }
// We have a real environment table, but no unsetenv? Fake it w/ putenv. // We have a real environment table, but no unsetenv? Fake it w/ putenv.
#else #else
int SDL_unsetenv(const char *name) int SDL_unsetenv_unsafe(const char *name)
{ {
// Input validation // Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
@ -187,7 +200,7 @@ int SDL_unsetenv(const char *name)
} }
#endif #endif
#elif defined(HAVE_WIN32_ENVIRONMENT) #elif defined(HAVE_WIN32_ENVIRONMENT)
int SDL_unsetenv(const char *name) int SDL_unsetenv_unsafe(const char *name)
{ {
// Input validation // Input validation
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) { if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
@ -200,7 +213,7 @@ int SDL_unsetenv(const char *name)
return 0; return 0;
} }
#else #else
int SDL_unsetenv(const char *name) int SDL_unsetenv_unsafe(const char *name)
{ {
size_t len, i; size_t len, i;
@ -226,7 +239,7 @@ int SDL_unsetenv(const char *name)
// Retrieve a variable named "name" from the environment // Retrieve a variable named "name" from the environment
#ifdef HAVE_LIBC_ENVIRONMENT #ifdef HAVE_LIBC_ENVIRONMENT
const char *SDL_getenv(const char *name) const char *SDL_getenv_unsafe(const char *name)
{ {
#ifdef SDL_PLATFORM_ANDROID #ifdef SDL_PLATFORM_ANDROID
// Make sure variables from the application manifest are available // Make sure variables from the application manifest are available
@ -241,7 +254,7 @@ const char *SDL_getenv(const char *name)
return getenv(name); return getenv(name);
} }
#elif defined(HAVE_WIN32_ENVIRONMENT) #elif defined(HAVE_WIN32_ENVIRONMENT)
const char *SDL_getenv(const char *name) const char *SDL_getenv_unsafe(const char *name)
{ {
DWORD length, maxlen = 0; DWORD length, maxlen = 0;
char *string = NULL; char *string = NULL;
@ -280,7 +293,7 @@ const char *SDL_getenv(const char *name)
return result; return result;
} }
#else #else
const char *SDL_getenv(const char *name) const char *SDL_getenv_unsafe(const char *name)
{ {
size_t len, i; size_t len, i;
char *value; char *value;
@ -304,3 +317,244 @@ const char *SDL_getenv(const char *name)
return value; return value;
} }
#endif // HAVE_LIBC_ENVIRONMENT #endif // HAVE_LIBC_ENVIRONMENT
struct SDL_Environment
{
SDL_Mutex *lock;
SDL_HashTable *strings;
};
static SDL_Environment *SDL_environment;
SDL_Environment *SDL_GetEnvironment(void)
{
if (!SDL_environment) {
SDL_environment = SDL_CreateEnvironment(false);
}
return SDL_environment;
}
void SDL_CleanupEnvironment(void)
{
SDL_Environment *env = SDL_environment;
if (env) {
SDL_environment = NULL;
SDL_DestroyEnvironment(env);
}
}
SDL_Environment *SDL_CreateEnvironment(SDL_bool empty)
{
SDL_Environment *env = SDL_calloc(1, sizeof(*env));
if (!env) {
return NULL;
}
env->strings = SDL_CreateHashTable(NULL, 16, SDL_HashString, SDL_KeyMatchString, SDL_NukeFreeKey, false);
if (!env->strings) {
SDL_free(env);
return NULL;
}
// Don't fail if we can't create a mutex (e.g. on a single-thread environment)
env->lock = SDL_CreateMutex();
if (!empty) {
#ifdef SDL_PLATFORM_WINDOWS
LPWCH strings = GetEnvironmentStringsW();
if (strings) {
for (LPWCH string = strings; *string; string += SDL_wcslen(string) + 1) {
char *variable = WIN_StringToUTF8W(string);
if (!variable) {
continue;
}
char *value = SDL_strchr(variable, '=');
if (!value || value == variable) {
SDL_free(variable);
continue;
}
*value++ = '\0';
SDL_InsertIntoHashTable(env->strings, variable, value);
}
FreeEnvironmentStringsW(strings);
}
#else
#ifdef SDL_PLATFORM_ANDROID
// Make sure variables from the application manifest are available
Android_JNI_GetManifestEnvironmentVariables();
#endif
char **strings = environ;
for (int i = 0; strings[i]; ++i) {
char *variable = SDL_strdup(strings[i]);
if (!variable) {
continue;
}
char *value = SDL_strchr(variable, '=');
if (!value || value == variable) {
SDL_free(variable);
continue;
}
*value++ = '\0';
SDL_InsertIntoHashTable(env->strings, variable, value);
}
#endif // SDL_PLATFORM_WINDOWS
}
return env;
}
const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name)
{
const char *result = NULL;
if (!env) {
return NULL;
} else if (!name || *name == '\0') {
return NULL;
}
SDL_LockMutex(env->lock);
{
const char *value;
if (SDL_FindInHashTable(env->strings, name, (const void **)&value)) {
result = SDL_GetPersistentString(value);
}
}
SDL_UnlockMutex(env->lock);
return result;
}
char **SDL_GetEnvironmentVariables(SDL_Environment *env)
{
char **result = NULL;
if (!env) {
SDL_InvalidParamError("env");
return NULL;
}
SDL_LockMutex(env->lock);
{
size_t count, length = 0;
void *iter;
const char *key, *value;
// First pass, get the size we need for all the strings
count = 0;
iter = NULL;
while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
length += SDL_strlen(key) + 1 + SDL_strlen(value) + 1;
++count;
}
// Allocate memory for the strings
result = (char **)SDL_malloc((count + 1) * sizeof(*result) + length);
char *string = (char *)(result + count + 1);
// Second pass, copy the strings
count = 0;
iter = NULL;
while (SDL_IterateHashTable(env->strings, (const void **)&key, (const void **)&value, &iter)) {
size_t len;
result[count] = string;
len = SDL_strlen(key);
SDL_memcpy(string, key, len);
string += len;
*string++ = '=';
len = SDL_strlen(value);
SDL_memcpy(string, value, len);
string += len;
*string++ = '\0';
++count;
}
result[count] = NULL;
}
SDL_UnlockMutex(env->lock);
return result;
}
SDL_bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, SDL_bool overwrite)
{
bool result = false;
if (!env) {
return SDL_InvalidParamError("env");
} else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
return SDL_InvalidParamError("name");
} else if (!value) {
return SDL_InvalidParamError("value");
}
SDL_LockMutex(env->lock);
{
const void *existing_value;
bool insert = true;
if (SDL_FindInHashTable(env->strings, name, &existing_value)) {
if (!overwrite) {
result = true;
insert = false;
} else {
SDL_RemoveFromHashTable(env->strings, name);
}
}
if (insert) {
char *string = NULL;
if (SDL_asprintf(&string, "%s=%s", name, value) > 0) {
size_t len = SDL_strlen(name);
string[len] = '\0';
name = string;
value = string + len + 1;
result = SDL_InsertIntoHashTable(env->strings, name, value);
}
}
}
SDL_UnlockMutex(env->lock);
return result;
}
SDL_bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name)
{
bool result = false;
if (!env) {
return SDL_InvalidParamError("env");
} else if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL) {
return SDL_InvalidParamError("name");
}
SDL_LockMutex(env->lock);
{
const void *value;
if (SDL_FindInHashTable(env->strings, name, &value)) {
result = SDL_RemoveFromHashTable(env->strings, name);
} else {
result = true;
}
}
SDL_UnlockMutex(env->lock);
return result;
}
void SDL_DestroyEnvironment(SDL_Environment *env)
{
if (!env || env == SDL_environment) {
return;
}
SDL_DestroyMutex(env->lock);
SDL_DestroyHashTable(env->strings);
SDL_free(env);
}

View file

@ -163,15 +163,15 @@ static const char *getlocale(char *buffer, size_t bufsize)
const char *lang; const char *lang;
char *ptr; char *ptr;
lang = SDL_getenv("LC_ALL"); lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_ALL");
if (!lang) { if (!lang) {
lang = SDL_getenv("LC_CTYPE"); lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_CTYPE");
} }
if (!lang) { if (!lang) {
lang = SDL_getenv("LC_MESSAGES"); lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_MESSAGES");
} }
if (!lang) { if (!lang) {
lang = SDL_getenv("LANG"); lang = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG");
} }
if (!lang || !*lang || SDL_strcmp(lang, "C") == 0) { if (!lang || !*lang || SDL_strcmp(lang, "C") == 0) {
lang = "ASCII"; lang = "ASCII";

View file

@ -299,7 +299,7 @@ void SDLTest_TrackAllocations(void)
#ifdef SDLTEST_UNWIND_NO_PROC_NAME_BY_IP #ifdef SDLTEST_UNWIND_NO_PROC_NAME_BY_IP
do { do {
/* Don't use SDL_GetHint: SDL_malloc is off limits. */ /* Don't use SDL_GetHint: SDL_malloc is off limits. */
const char *env_trackmem = SDL_getenv("SDL_TRACKMEM_SYMBOL_NAMES"); const char *env_trackmem = SDL_getenv_unsafe("SDL_TRACKMEM_SYMBOL_NAMES");
if (env_trackmem) { if (env_trackmem) {
if (SDL_strcasecmp(env_trackmem, "1") == 0 || SDL_strcasecmp(env_trackmem, "yes") == 0 || SDL_strcasecmp(env_trackmem, "true") == 0) { if (SDL_strcasecmp(env_trackmem, "1") == 0 || SDL_strcasecmp(env_trackmem, "yes") == 0 || SDL_strcasecmp(env_trackmem, "true") == 0) {
s_unwind_symbol_names = SDL_TRUE; s_unwind_symbol_names = SDL_TRUE;

View file

@ -341,7 +341,7 @@ static bool SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_
#if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA) #if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA)
/* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */ /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); path = SDL_getenv_unsafe("SDL_VIDEO_GL_DRIVER");
if (path) { if (path) {
opengl_dll_handle = SDL_LoadObject(path); opengl_dll_handle = SDL_LoadObject(path);
} }
@ -401,7 +401,7 @@ static bool SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_
if (egl_dll_handle) { if (egl_dll_handle) {
SDL_UnloadObject(egl_dll_handle); SDL_UnloadObject(egl_dll_handle);
} }
path = SDL_getenv("SDL_VIDEO_EGL_DRIVER"); path = SDL_getenv_unsafe("SDL_VIDEO_EGL_DRIVER");
if (!path) { if (!path) {
path = DEFAULT_EGL; path = DEFAULT_EGL;
} }

View file

@ -1292,11 +1292,11 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
*/ */
// Look up the preferred locale, falling back to "C" as default // Look up the preferred locale, falling back to "C" as default
locale = SDL_getenv("LC_ALL"); locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_ALL");
if (!locale) { if (!locale) {
locale = SDL_getenv("LC_CTYPE"); locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LC_CTYPE");
if (!locale) { if (!locale) {
locale = SDL_getenv("LANG"); locale = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "LANG");
if (!locale) { if (!locale) {
locale = "C"; locale = "C";
} }

View file

@ -141,8 +141,8 @@ bool Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *butto
}; };
// Are we trying to connect to or are currently in a Wayland session? // Are we trying to connect to or are currently in a Wayland session?
if (!SDL_getenv("WAYLAND_DISPLAY")) { if (!SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "WAYLAND_DISPLAY")) {
const char *session = SDL_getenv("XDG_SESSION_TYPE"); const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session && SDL_strcasecmp(session, "wayland") != 0) { if (session && SDL_strcasecmp(session, "wayland") != 0) {
return SDL_SetError("Not on a wayland display"); return SDL_SetError("Not on a wayland display");
} }

View file

@ -345,7 +345,7 @@ static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdat
// Fallback envvar if the DBus properties don't exist // Fallback envvar if the DBus properties don't exist
if (size <= 0) { if (size <= 0) {
const char *xcursor_size = SDL_getenv("XCURSOR_SIZE"); const char *xcursor_size = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XCURSOR_SIZE");
if (xcursor_size) { if (xcursor_size) {
size = SDL_atoi(xcursor_size); size = SDL_atoi(xcursor_size);
} }
@ -381,7 +381,7 @@ static bool wayland_get_system_cursor(SDL_VideoData *vdata, SDL_CursorData *cdat
// Fallback envvar if the DBus properties don't exist // Fallback envvar if the DBus properties don't exist
if (!xcursor_theme) { if (!xcursor_theme) {
xcursor_theme = SDL_getenv("XCURSOR_THEME"); xcursor_theme = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XCURSOR_THEME");
} }
theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, size, vdata->shm); theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, size, vdata->shm);

View file

@ -80,7 +80,7 @@ static int CreateTempFD(off_t size)
const char *xdg_path; const char *xdg_path;
char tmp_path[PATH_MAX]; char tmp_path[PATH_MAX];
xdg_path = SDL_getenv("XDG_RUNTIME_DIR"); xdg_path = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_RUNTIME_DIR");
if (!xdg_path) { if (!xdg_path) {
return -1; return -1;
} }

View file

@ -429,8 +429,8 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
bool display_is_external = !!display; bool display_is_external = !!display;
// Are we trying to connect to or are currently in a Wayland session? // Are we trying to connect to or are currently in a Wayland session?
if (!SDL_getenv("WAYLAND_DISPLAY")) { if (!SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "WAYLAND_DISPLAY")) {
const char *session = SDL_getenv("XDG_SESSION_TYPE"); const char *session = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session && SDL_strcasecmp(session, "wayland") != 0) { if (session && SDL_strcasecmp(session, "wayland") != 0) {
return NULL; return NULL;
} }

View file

@ -1914,14 +1914,14 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
/* Note that we don't check for empty strings, as that is still /* Note that we don't check for empty strings, as that is still
* considered a valid activation token! * considered a valid activation token!
*/ */
const char *activation_token = SDL_getenv("XDG_ACTIVATION_TOKEN"); const char *activation_token = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_ACTIVATION_TOKEN");
if (activation_token) { if (activation_token) {
xdg_activation_v1_activate(c->activation_manager, xdg_activation_v1_activate(c->activation_manager,
activation_token, activation_token,
data->surface); data->surface);
// Clear this variable, per the protocol's request // Clear this variable, per the protocol's request
SDL_unsetenv("XDG_ACTIVATION_TOKEN"); SDL_unsetenv_unsafe("XDG_ACTIVATION_TOKEN");
} }
} }

View file

@ -169,7 +169,7 @@ bool X11_InitKeyboard(SDL_VideoDevice *_this)
char *prev_locale = setlocale(LC_ALL, NULL); char *prev_locale = setlocale(LC_ALL, NULL);
char *prev_xmods = X11_XSetLocaleModifiers(NULL); char *prev_xmods = X11_XSetLocaleModifiers(NULL);
const char *new_xmods = ""; const char *new_xmods = "";
const char *env_xmods = SDL_getenv("XMODIFIERS"); const char *env_xmods = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XMODIFIERS");
bool has_dbus_ime_support = false; bool has_dbus_ime_support = false;
if (prev_locale) { if (prev_locale) {

View file

@ -248,7 +248,7 @@ static float GetGlobalContentScale(SDL_VideoDevice *_this)
// If that failed, try the GDK_SCALE envvar... // If that failed, try the GDK_SCALE envvar...
if (scale_factor <= 0.0) { if (scale_factor <= 0.0) {
const char *scale_str = SDL_getenv("GDK_SCALE"); const char *scale_str = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "GDK_SCALE");
if (scale_str) { if (scale_str) {
scale_factor = SDL_atoi(scale_str); scale_factor = SDL_atoi(scale_str);
} }

View file

@ -5,14 +5,6 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#if defined(SDL_PLATFORM_WINDOWS)
#include <windows.h>
#elif defined(SDL_PLATFORM_MACOS)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
SDLTest_CommonState *state; SDLTest_CommonState *state;
@ -95,26 +87,18 @@ int main(int argc, char *argv[]) {
} }
if (print_environment || expect_environment) { if (print_environment || expect_environment) {
char **env = SDL_GetEnvironmentVariables(SDL_GetEnvironment());
#if defined(SDL_PLATFORM_WINDOWS) if (env) {
char *original_env = GetEnvironmentStrings(); for (i = 0; env[i]; ++i) {
const char *env = original_env; if (print_environment) {
for (; env[0]; env += SDL_strlen(env) + 1) { fprintf(stdout, "%s\n", env[i]);
#else }
char **envp = environ; if (expect_environment) {
for (; *envp; envp++) { expect_environment_match |= SDL_strcmp(env[i], expect_environment) == 0;
const char *env = *envp; }
#endif
if (print_environment) {
fprintf(stdout, "%s\n", env);
}
if (expect_environment) {
expect_environment_match |= SDL_strcmp(env, expect_environment) == 0;
} }
SDL_free(env);
} }
#ifdef SDL_PLATFORM_WINDOWS
FreeEnvironmentStringsA(original_env);
#endif
} }
if (stdin_to_stdout || stdin_to_stderr) { if (stdin_to_stdout || stdin_to_stderr) {

View file

@ -740,7 +740,7 @@ int main(int argc, char *argv[])
RunBasicTest(); RunBasicTest();
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests"); SDL_Log("Not running slower tests");
return 0; return 0;
} }

View file

@ -130,7 +130,7 @@ static int SDLCALL hints_setHint(void *arg)
SDL_free(value); SDL_free(value);
/* Set default value in environment */ /* Set default value in environment */
SDL_setenv(testHint, "original", 1); SDL_SetEnvironmentVariable(SDL_GetEnvironment(), testHint, "original", 1);
SDLTest_AssertPass("Call to SDL_GetHint() after saving and restoring hint"); SDLTest_AssertPass("Call to SDL_GetHint() after saving and restoring hint");
originalValue = SDL_GetHint(testHint); originalValue = SDL_GetHint(testHint);

View file

@ -542,10 +542,11 @@ static int SDLCALL stdlib_swprintf(void *arg)
#endif #endif
/** /**
* Call to SDL_getenv and SDL_setenv * Call to SDL_GetEnvironmentVariable() and SDL_SetEnvironmentVariable()
*/ */
static int SDLCALL stdlib_getsetenv(void *arg) static int SDLCALL stdlib_getsetenv(void *arg)
{ {
SDL_Environment *env = SDL_GetEnvironment();
const int nameLen = 16; const int nameLen = 16;
char name[17]; char name[17];
int counter; int counter;
@ -556,7 +557,7 @@ static int SDLCALL stdlib_getsetenv(void *arg)
int overwrite; int overwrite;
const char *text; const char *text;
/* Create a random name. This tests SDL_getenv, since we need to */ /* Create a random name. This tests SDL_GetEnvironmentVariable, since we need to */
/* make sure the variable is not set yet (it shouldn't). */ /* make sure the variable is not set yet (it shouldn't). */
do { do {
for (counter = 0; counter < nameLen; counter++) { for (counter = 0; counter < nameLen; counter++) {
@ -564,8 +565,8 @@ static int SDLCALL stdlib_getsetenv(void *arg)
} }
name[nameLen] = '\0'; name[nameLen] = '\0';
text = SDL_getenv(name); text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
if (text) { if (text) {
SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, (int)SDL_strlen(text)); SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, (int)SDL_strlen(text));
} }
@ -578,13 +579,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 1 without overwrite */ /* Set value 1 without overwrite */
overwrite = 0; overwrite = 0;
expected = value1; expected = value1;
result = SDL_setenv(name, value1, overwrite); result = SDL_SetEnvironmentVariable(env, name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */ /* Check value */
text = SDL_getenv(name); text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) { if (text != NULL) {
SDLTest_AssertCheck( SDLTest_AssertCheck(
@ -597,13 +598,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 2 with overwrite */ /* Set value 2 with overwrite */
overwrite = 1; overwrite = 1;
expected = value2; expected = value2;
result = SDL_setenv(name, value2, overwrite); result = SDL_SetEnvironmentVariable(env, name, value2, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value2, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value2, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */ /* Check value */
text = SDL_getenv(name); text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) { if (text != NULL) {
SDLTest_AssertCheck( SDLTest_AssertCheck(
@ -616,13 +617,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 1 without overwrite */ /* Set value 1 without overwrite */
overwrite = 0; overwrite = 0;
expected = value2; expected = value2;
result = SDL_setenv(name, value1, overwrite); result = SDL_SetEnvironmentVariable(env, name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */ /* Check value */
text = SDL_getenv(name); text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) { if (text != NULL) {
SDLTest_AssertCheck( SDLTest_AssertCheck(
@ -635,13 +636,13 @@ static int SDLCALL stdlib_getsetenv(void *arg)
/* Set value 1 with overwrite */ /* Set value 1 with overwrite */
overwrite = 1; overwrite = 1;
expected = value1; expected = value1;
result = SDL_setenv(name, value1, overwrite); result = SDL_SetEnvironmentVariable(env, name, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s','%s', %i)", name, value1, overwrite);
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
/* Check value */ /* Check value */
text = SDL_getenv(name); text = SDL_GetEnvironmentVariable(env, name);
SDLTest_AssertPass("Call to SDL_getenv('%s')", name); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, '%s')", name);
SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL"); SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
if (text != NULL) { if (text != NULL) {
SDLTest_AssertCheck( SDLTest_AssertCheck(
@ -652,48 +653,48 @@ static int SDLCALL stdlib_getsetenv(void *arg)
} }
/* Verify setenv() with empty string vs unsetenv() */ /* Verify setenv() with empty string vs unsetenv() */
result = SDL_setenv("FOO", "1", 1); result = SDL_SetEnvironmentVariable(env, "FOO", "1", 1);
SDLTest_AssertPass("Call to SDL_setenv('FOO','1', 1)"); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','1', 1)");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
expected = "1"; expected = "1";
text = SDL_getenv("FOO"); text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')"); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text); SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text);
result = SDL_setenv("FOO", "", 1); result = SDL_SetEnvironmentVariable(env, "FOO", "", 1);
SDLTest_AssertPass("Call to SDL_setenv('FOO','', 1)"); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','', 1)");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
expected = ""; expected = "";
text = SDL_getenv("FOO"); text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')"); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: '%s', got: '%s'", expected, text); SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: '%s', got: '%s'", expected, text);
result = SDL_unsetenv("FOO"); result = SDL_UnsetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_unsetenv('FOO')"); SDLTest_AssertPass("Call to SDL_UnsetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
text = SDL_getenv("FOO"); text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')"); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text == NULL, "Verify returned text, expected: (null), got: %s", text); SDLTest_AssertCheck(text == NULL, "Verify returned text, expected: (null), got: %s", text);
result = SDL_setenv("FOO", "0", 0); result = SDL_SetEnvironmentVariable(env, "FOO", "0", 0);
SDLTest_AssertPass("Call to SDL_setenv('FOO','0', 0)"); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, 'FOO','0', 0)");
SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result); SDLTest_AssertCheck(result == SDL_TRUE, "Check result, expected: 1, got: %i", result);
expected = "0"; expected = "0";
text = SDL_getenv("FOO"); text = SDL_GetEnvironmentVariable(env, "FOO");
SDLTest_AssertPass("Call to SDL_getenv('FOO')"); SDLTest_AssertPass("Call to SDL_GetEnvironmentVariable(env, 'FOO')");
SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text); SDLTest_AssertCheck(text && SDL_strcmp(text, expected) == 0, "Verify returned text, expected: %s, got: %s", expected, text);
/* Negative cases */ /* Negative cases */
for (overwrite = 0; overwrite <= 1; overwrite++) { for (overwrite = 0; overwrite <= 1; overwrite++) {
result = SDL_setenv(NULL, value1, overwrite); result = SDL_SetEnvironmentVariable(env, NULL, value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv(NULL,'%s', %i)", value1, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, NULL,'%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
result = SDL_setenv("", value1, overwrite); result = SDL_SetEnvironmentVariable(env, "", value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('','%s', %i)", value1, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '','%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
result = SDL_setenv("=", value1, overwrite); result = SDL_SetEnvironmentVariable(env, "=", value1, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('=','%s', %i)", value1, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '=','%s', %i)", value1, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
result = SDL_setenv(name, NULL, overwrite); result = SDL_SetEnvironmentVariable(env, name, NULL, overwrite);
SDLTest_AssertPass("Call to SDL_setenv('%s', NULL, %i)", name, overwrite); SDLTest_AssertPass("Call to SDL_SetEnvironmentVariable(env, '%s', NULL, %i)", name, overwrite);
SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result); SDLTest_AssertCheck(result == SDL_FALSE, "Check result, expected: 0, got: %i", result);
} }
/* Clean up */ /* Clean up */
@ -1402,7 +1403,7 @@ static const SDLTest_TestCaseReference stdlibTest_swprintf = {
}; };
static const SDLTest_TestCaseReference stdlibTest_getsetenv = { static const SDLTest_TestCaseReference stdlibTest_getsetenv = {
stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_GetEnvironmentVariable and SDL_SetEnvironmentVariable", TEST_ENABLED
}; };
static const SDLTest_TestCaseReference stdlibTest_sscanf = { static const SDLTest_TestCaseReference stdlibTest_sscanf = {

View file

@ -43,7 +43,7 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title)
needs_renderer = SDL_TRUE; needs_renderer = SDL_TRUE;
} else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
/* Try to detect if the x11 driver is running under XWayland */ /* Try to detect if the x11 driver is running under XWayland */
const char *session_type = SDL_getenv("XDG_SESSION_TYPE"); const char *session_type = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_SESSION_TYPE");
if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) { if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) {
needs_renderer = SDL_TRUE; needs_renderer = SDL_TRUE;
} }
@ -1929,7 +1929,7 @@ static int SDLCALL video_getSetWindowState(void *arg)
* Other desktops can be enabled in the future as required. * Other desktops can be enabled in the future as required.
*/ */
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0 || SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0 || SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
const char *desktop = SDL_getenv("XDG_CURRENT_DESKTOP"); const char *desktop = SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "XDG_CURRENT_DESKTOP");
if (SDL_strcmp(desktop, "GNOME") != 0 && SDL_strcmp(desktop, "KDE") != 0) { if (SDL_strcmp(desktop, "GNOME") != 0 && SDL_strcmp(desktop, "KDE") != 0) {
SDLTest_Log("Skipping test video_getSetWindowState: desktop environment %s not supported", desktop); SDLTest_Log("Skipping test video_getSetWindowState: desktop environment %s not supported", desktop);
return TEST_SKIPPED; return TEST_SKIPPED;

View file

@ -93,7 +93,7 @@ int main(int argc, char *argv[])
/* Set the error value for the main thread */ /* Set the error value for the main thread */
SDL_SetError("No worries"); SDL_SetError("No worries");
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests"); SDL_Log("Not running slower tests");
SDL_Quit(); SDL_Quit();
return 0; return 0;

View file

@ -35,39 +35,35 @@ static void SDLCALL setUpProcess(void **arg) {
static const char *options[] = { "/path/to/childprocess" EXE, NULL }; static const char *options[] = { "/path/to/childprocess" EXE, NULL };
static char *env_key_val_string(const char *key) {
const char *env = SDL_getenv(key);
size_t size_result;
char *result;
if (env == NULL) {
return NULL;
}
size_result = SDL_strlen(key) + SDL_strlen(env) + 2;
result = SDL_malloc(size_result);
SDL_snprintf(result, size_result, "%s=%s", key, env);
return result;
}
static char **DuplicateEnvironment(const char *key0, ...) static char **DuplicateEnvironment(const char *key0, ...)
{ {
va_list ap; va_list ap;
size_t count = 1;
size_t i;
const char *keyN; const char *keyN;
SDL_Environment *env = SDL_GetEnvironment();
SDL_Environment *new_env = SDL_CreateEnvironment(SDL_TRUE);
char **result; char **result;
if (key0) { if (key0) {
if (SDL_strchr(key0, '=') || SDL_getenv(key0)) { char *sep = SDL_strchr(key0, '=');
count += 1; if (sep) {
*sep = '\0';
SDL_SetEnvironmentVariable(new_env, key0, sep + 1, SDL_TRUE);
*sep = '=';
SDL_SetEnvironmentVariable(new_env, key0, sep, SDL_TRUE);
} else {
SDL_SetEnvironmentVariable(new_env, key0, SDL_GetEnvironmentVariable(env, key0), SDL_TRUE);
} }
va_start(ap, key0); va_start(ap, key0);
for (;;) { for (;;) {
keyN = va_arg(ap, const char *); keyN = va_arg(ap, const char *);
if (keyN) { if (keyN) {
if (SDL_strchr(keyN, '=') || SDL_getenv(keyN)) { sep = SDL_strchr(keyN, '=');
count += 1; if (sep) {
*sep = '\0';
SDL_SetEnvironmentVariable(new_env, keyN, sep + 1, SDL_TRUE);
*sep = '=';
} else {
SDL_SetEnvironmentVariable(new_env, keyN, SDL_GetEnvironmentVariable(env, keyN), SDL_TRUE);
} }
} else { } else {
break; break;
@ -76,45 +72,11 @@ static char **DuplicateEnvironment(const char *key0, ...)
va_end(ap); va_end(ap);
} }
result = SDL_calloc(count, sizeof(char *)); result = SDL_GetEnvironmentVariables(new_env);
SDL_DestroyEnvironment(new_env);
i = 0;
if (key0) {
if (SDL_strchr(key0, '=')) {
result[i++] = SDL_strdup(key0);
} else if (SDL_getenv(key0)) {
result[i++] = env_key_val_string(key0);
}
va_start(ap, key0);
for (;;) {
keyN = va_arg(ap, const char *);
if (keyN) {
if (SDL_strchr(keyN, '=')) {
result[i++] = SDL_strdup(keyN);
} else if (SDL_getenv(keyN)) {
result[i++] = env_key_val_string(keyN);
}
} else {
break;
}
}
va_end(ap);
}
return result; return result;
} }
static void DestroyEnvironment(char **environment) {
char **envp;
if (!environment) {
return;
}
for (envp = environment; *envp; envp++) {
SDL_free(*envp);
}
SDL_free(environment);
}
static int SDLCALL process_testArguments(void *arg) static int SDLCALL process_testArguments(void *arg)
{ {
TestProcessData *data = (TestProcessData *)arg; TestProcessData *data = (TestProcessData *)arg;
@ -187,7 +149,7 @@ static int SDLCALL process_testInheritedEnv(void *arg)
test_env_val = SDLTest_RandomAsciiStringOfSize(32); test_env_val = SDLTest_RandomAsciiStringOfSize(32);
SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY, test_env_val); SDLTest_AssertPass("Setting parent environment variable %s=%s", TEST_ENV_KEY, test_env_val);
SDL_setenv(TEST_ENV_KEY, test_env_val, 1); SDL_SetEnvironmentVariable(SDL_GetEnvironment(), TEST_ENV_KEY, test_env_val, SDL_TRUE);
SDL_snprintf(buffer, sizeof(buffer), "%s=%s", TEST_ENV_KEY, test_env_val); SDL_snprintf(buffer, sizeof(buffer), "%s=%s", TEST_ENV_KEY, test_env_val);
process_args[3] = buffer; process_args[3] = buffer;
@ -312,13 +274,14 @@ static int SDLCALL process_testNewEnv(void *arg)
SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code); SDLTest_AssertCheck(exit_code == 0, "Exit code should be 0, is %d", exit_code);
SDLTest_AssertPass("About to destroy process"); SDLTest_AssertPass("About to destroy process");
SDL_DestroyProcess(process); SDL_DestroyProcess(process);
DestroyEnvironment(process_env); SDL_free(process_env);
SDL_free(test_env_val); SDL_free(test_env_val);
return TEST_COMPLETED; return TEST_COMPLETED;
failed: failed:
SDL_free(test_env_val); SDL_free(test_env_val);
SDL_DestroyProcess(process); SDL_DestroyProcess(process);
DestroyEnvironment(process_env); SDL_free(process_env);
return TEST_ABORTED; return TEST_ABORTED;
} }
@ -330,7 +293,6 @@ static int process_testStdinToStdout(void *arg)
"--stdin-to-stdout", "--stdin-to-stdout",
NULL, NULL,
}; };
const char **process_env = NULL;
SDL_PropertiesID props; SDL_PropertiesID props;
SDL_Process *process = NULL; SDL_Process *process = NULL;
Sint64 pid; Sint64 pid;
@ -346,7 +308,6 @@ static int process_testStdinToStdout(void *arg)
props = SDL_CreateProperties(); props = SDL_CreateProperties();
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args); SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, (void *)process_args);
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, (void *)process_env);
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP); SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_APP);
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP); SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
process = SDL_CreateProcessWithProperties(props); process = SDL_CreateProcessWithProperties(props);

View file

@ -223,7 +223,7 @@ int main(int argc, char *argv[])
SDL_Log("Playing %d Hz test tone on channel: %s\n", sine_freq, get_channel_name(j, total_channels)); SDL_Log("Playing %d Hz test tone on channel: %s\n", sine_freq, get_channel_name(j, total_channels));
/* fill_buffer() will increment the active channel */ /* fill_buffer() will increment the active channel */
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Delay(QUICK_TEST_TIME_MSEC); SDL_Delay(QUICK_TEST_TIME_MSEC);
} else { } else {
SDL_Delay(CHANNEL_TEST_TIME_SEC * 1000); SDL_Delay(CHANNEL_TEST_TIME_SEC * 1000);

View file

@ -127,7 +127,7 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests"); SDL_Log("Not running slower tests");
SDL_Quit(); SDL_Quit();
return 0; return 0;

View file

@ -124,7 +124,7 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) { if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
SDL_Log("Not running slower tests"); SDL_Log("Not running slower tests");
SDL_Quit(); SDL_Quit();
return 0; return 0;