sdl12-compat: Try to match the real SDL 1.2's SDL_stdinc.h better.

From 0ee4f10758968cde8021ed8508679f3a6bae3649 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 1 Jun 2021 09:43:26 -0400
Subject: [PATCH] Try to match the real SDL 1.2's SDL_stdinc.h better.

Now we try to `#define SDL_fn fn` instead of provide a function declaration
for common things. sdl12-compat always provides the symbols, but this lets
apps compiled with these headers work with an actual build of SDL 1.2 that
might not, because it expected the app to use those macros to reference the
C runtime directly.

This is imperfect because we are trying to do this without a configure stage
for these headers, but it probably already covers most of what we care about
well...but we'll definitely need some #ifdef tweaks for things that aren't
a standardish desktop Linux system...but it's also possible we care less
about binary compatibility with real SDL 1.2 on those targets.

Fixes #73.
(more or less.)
---
 include/SDL/SDL_config.h |  80 +++++++-----
 include/SDL/SDL_stdinc.h | 261 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 306 insertions(+), 35 deletions(-)

diff --git a/include/SDL/SDL_config.h b/include/SDL/SDL_config.h
index 3a05424..eb7fe47 100644
--- a/include/SDL/SDL_config.h
+++ b/include/SDL/SDL_config.h
@@ -54,6 +54,10 @@ typedef unsigned __int64 uint64_t;
 #include <stdarg.h>
 #define HAVE_STDARG_H 1
 
+/* for now, let's try and say everything that we care about that isn't Windows
+has these C runtime functions available. We're trying to avoid a configure
+stage, though. Send patches if your platform lacks something. */
+#ifndef _WIN32
 #define HAVE_LIBC 1
 #define HAVE_ALLOCA_H 1
 #define HAVE_SYS_TYPES_H 1
@@ -67,6 +71,7 @@ typedef unsigned __int64 uint64_t;
 #define HAVE_INTTYPES_H 1
 #define HAVE_CTYPE_H 1
 #define HAVE_MATH_H 1
+#endif
 
 #if defined(unix)
 #define HAVE_ICONV_H 1
@@ -77,72 +82,85 @@ typedef unsigned __int64 uint64_t;
 #define HAVE_ALTIVEC_H 1
 #endif
 
+/* SDL 1.2 never defines these for Windows to force SDL's internal implementation. */
+#ifndef _WIN32
+#define HAVE_GETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#endif
+
+/* for now, let's try and say everything that we care about that isn't Windows
+has these C runtime functions available. We're trying to avoid a configure
+stage, though. Send patches if your platform lacks something. */
+#ifndef _WIN32
 #define HAVE_MALLOC 1
 #define HAVE_CALLOC 1
 #define HAVE_REALLOC 1
 #define HAVE_FREE 1
 #define HAVE_ALLOCA 1
-#ifndef _WIN32  /* SDL 1.2 never defines these for Windows to force SDL's internal implementation. */
-#define HAVE_GETENV 1
-#define HAVE_PUTENV 1
-#define HAVE_UNSETENV 1
-#endif
 #define HAVE_QSORT 1
 #define HAVE_ABS 1
-#define HAVE_BCOPY 1
 #define HAVE_MEMSET 1
 #define HAVE_MEMCPY 1
 #define HAVE_MEMMOVE 1
 #define HAVE_MEMCMP 1
 #define HAVE_STRLEN 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_SSCANF 1
+#ifndef __WATCOMC__ /* apparently Watcom C's snprintf is not to be trusted... */
+#define HAVE_SNPRINTF 1
+#define HAVE_VSNPRINTF 1
+#endif
+#endif
+
+/* things that aren't necessarily in Linux, some are MSVC C runtime, some are BSD. Send patches. */
+#if 0
+#define HAVE_BCOPY 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
 #define HAVE_STRLCPY 1
 #define HAVE_STRLCAT 1
-#define HAVE_STRDUP 1
 #define HAVE__STRREV 1
 #define HAVE__STRUPR 1
 #define HAVE__STRLWR 1
 #define HAVE_INDEX 1
 #define HAVE_RINDEX 1
-#define HAVE_STRCHR 1
-#define HAVE_STRRCHR 1
-#define HAVE_STRSTR 1
 #define HAVE_ITOA 1
 #define HAVE__LTOA 1
 #define HAVE__UITOA 1
 #define HAVE__ULTOA 1
-#define HAVE_STRTOL 1
-#define HAVE_STRTOUL 1
 #define HAVE__I64TOA 1
 #define HAVE__UI64TOA 1
-#define HAVE_STRTOLL 1
-#define HAVE_STRTOULL 1
 #define HAVE__STRTOI64 1
 #define HAVE__STRTOUI64 1
-#define HAVE_STRTOD 1
-#define HAVE_ATOI 1
-#define HAVE_ATOF 1
-#define HAVE_STRCMP 1
-#define HAVE_STRNCMP 1
 #define HAVE__STRICMP 1
-#define HAVE_STRCASECMP 1
 #define HAVE__STRNICMP 1
-#define HAVE_STRNCASECMP 1
-#define HAVE_SSCANF 1
-#define HAVE_SNPRINTF 1
-#define HAVE_VSNPRINTF 1
+#define HAVE_GETAUXVAL 1
+#define HAVE_ELF_AUX_INFO 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_CLOCK_GETTIME 1
+#define HAVE_GETPAGESIZE 1
+#define HAVE_MPROTECT 1
+#define HAVE_SEM_TIMEDWAIT 1
+#endif
 
 #ifdef unix
 #define HAVE_ICONV 1
 #define HAVE_SIGACTION 1
 #define HAVE_SA_SIGACTION 1
 #define HAVE_SETJMP 1
-#define HAVE_NANOSLEEP 1
-#define HAVE_CLOCK_GETTIME 1
-#define HAVE_GETPAGESIZE 1
-#define HAVE_MPROTECT 1
-#define HAVE_SEM_TIMEDWAIT 1
-#define HAVE_GETAUXVAL 1
-#define HAVE_ELF_AUX_INFO 1
 #endif
 
 /* Don't define any of the SDL backend, under the assumption checking for these against the headers won't work anyhow. */
diff --git a/include/SDL/SDL_stdinc.h b/include/SDL/SDL_stdinc.h
index 7ba9435..a6e364a 100644
--- a/include/SDL/SDL_stdinc.h
+++ b/include/SDL/SDL_stdinc.h
@@ -77,51 +77,294 @@ typedef enum SDL_DUMMY_ENUM
 
 SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int));
 
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
 #include "begin_code.h"
 
+/* sdl12-compat always supplies these functions, but the real SDL 1.2 might
+not, so we try to #define them to be the C runtime equivalents as possible,
+so things built with these headers will still run against the real SDL 1.2. */
+
+#ifdef HAVE_ICONV
+#define SDL_iconv_t iconv_t
+#define SDL_iconv_open iconv_open
+#define SDL_iconv_close iconv_close
+#else
 typedef struct _SDL_iconv_t *SDL_iconv_t;
 extern DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode, const char *fromcode);
+extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);
+#endif
 extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
 extern DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf, size_t inbytesleft);
-extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);
 
+#ifdef HAVE_MALLOC
+#define SDL_malloc malloc
+#else
 extern DECLSPEC void * SDLCALL SDL_malloc(size_t size);
+#endif
+
+#ifdef HAVE_CALLOC
+#define SDL_calloc calloc
+#else
 extern DECLSPEC void * SDLCALL SDL_calloc(size_t nmemb, size_t size);
+#endif
+
+#ifdef HAVE_REALLOC
+#define SDL_realloc realloc
+#else
 extern DECLSPEC void * SDLCALL SDL_realloc(void *mem, size_t size);
+#endif
+
+#ifdef HAVE_FREE
+#define SDL_free free
+#else
 extern DECLSPEC void SDLCALL SDL_free(void *mem);
+#endif
+
+#ifdef HAVE_GETENV
+#define SDL_getenv getenv
+#else
 extern DECLSPEC char * SDLCALL SDL_getenv(const char *name);
+#endif
+
+#ifdef HAVE_PUTENV
+#define SDL_putenv putenv
+#else
 extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
+#endif
+
+#ifdef HAVE_QSORT
+#define SDL_qsort qsort
+#else
 extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare)(const void *, const void *));
+#endif
+
+#ifdef HAVE_MEMSET
+#define SDL_memset memset
+#else
 extern DECLSPEC void * SDLCALL SDL_memset(void *dst, int c, size_t len);
+#endif
+
+#ifdef HAVE_MEMCPY
+#define SDL_memcpy memcpy
+#else
 extern DECLSPEC void * SDLCALL SDL_memcpy(void *dst, const void *src, size_t len);
+#endif
+
+#ifdef HAVE_REVCPY
+#define SDL_revcpy revcpy
+#else
 extern DECLSPEC void * SDLCALL SDL_revcpy(void *dst, const void *src, size_t len);
+#endif
+
+#ifdef HAVE_MEMCMP
+#define SDL_memcmp memcmp
+#else
 extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len);
+#endif
+
+#ifdef HAVE_STRLEN
+#define SDL_strlen strlen
+#else
 extern DECLSPEC size_t SDLCALL SDL_strlen(const char *string);
+#endif
+
+#ifdef HAVE_STRLCPY
+#define SDL_strlcpy strlcpy
+#else
 extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen);
+#endif
+
+#ifdef HAVE_STRLCAT
+#define SDL_strlcat strlcat
+#else
 extern DECLSPEC size_t SDLCALL SDL_strlcat(char *dst, const char *src, size_t maxlen);
+#endif
+
+#ifdef HAVE_STRDUP
+#define SDL_strdup strdup
+#else
 extern DECLSPEC char * SDLCALL SDL_strdup(const char *string);
+#endif
+
+#ifdef HAVE__STRREV
+#define SDL_strrev _strrev
+#else
 extern DECLSPEC char * SDLCALL SDL_strrev(char *string);
+#endif
+
+#ifdef HAVE__STRUPR
+#define SDL_strupr _strupr
+#else
 extern DECLSPEC char * SDLCALL SDL_strupr(char *string);
+#endif
+
+#ifdef HAVE__STRLWR
+#define SDL_strlwr _strlwr
+#else
 extern DECLSPEC char * SDLCALL SDL_strlwr(char *string);
+#endif
+
+#ifdef HAVE_STRCHR
+#define SDL_strchr strchr
+#else
 extern DECLSPEC char * SDLCALL SDL_strchr(const char *string, int c);
+#endif
+
+#ifdef HAVE_STRRCHR
+#define SDL_strrchr strrchr
+#else
 extern DECLSPEC char * SDLCALL SDL_strrchr(const char *string, int c);
+#endif
+
+#ifdef HAVE_STRSTR
+#define SDL_strstr strstr
+#else
 extern DECLSPEC char * SDLCALL SDL_strstr(const char *haystack, const char *needle);
+#endif
+
+#ifdef HAVE__LTOA
+#define SDL_ltoa _ltoa
+#else
 extern DECLSPEC char * SDLCALL SDL_ltoa(long value, char *string, int radix);
+#endif
+
+#ifdef HAVE__ULTOA
+#define SDL_ultoa _ultoa
+#else
 extern DECLSPEC char * SDLCALL SDL_ultoa(unsigned long value, char *string, int radix);
+#endif
+
+#ifdef HAVE_STRTOL
+#define SDL_strtol strtol
+#else
 extern DECLSPEC long SDLCALL SDL_strtol(const char *string, char **endp, int base);
+#endif
+
+#ifdef HAVE_STRTOUL
+#define SDL_strtoul strtoul
+#else
 extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *string, char **endp, int base);
+#endif
+
+#ifdef HAVE__I64TOA
+#define SDL_lltoa _i64toa
+#else
 extern DECLSPEC char* SDLCALL SDL_lltoa(Sint64 value, char *string, int radix);
+#endif
+
+#ifdef HAVE__UI64TOA
+#define SDL_ulltoa _ui64toa
+#else
 extern DECLSPEC char* SDLCALL SDL_ulltoa(Uint64 value, char *string, int radix);
+#endif
+
+#ifdef HAVE__STRTOI64
+#define SDL_strtoll _strtoi64
+#elif defined(HAVE_STRTOLL)
+#define SDL_strtoll strtoll
+#else
 extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *string, char **endp, int base);
+#endif
+
+#ifdef HAVE__STRTOUI64
+#define SDL_strtoull _strtoui64
+#elif defined(HAVE_STRTOULL)
+#define SDL_strtoull strtoull
+#else
 extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *string, char **endp, int base);
+#endif
+
+#ifdef HAVE_STRTOD
+#define SDL_strtod strtod
+#else
 extern DECLSPEC double SDLCALL SDL_strtod(const char *string, char **endp);
+#endif
+
+#ifdef HAVE_STRCMP
+#define SDL_strcmp strcmp
+#else
 extern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2);
+#endif
+
+#ifdef HAVE_STRNCMP
+#define SDL_strncmp strncmp
+#else
 extern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen);
+#endif
+
+#ifdef HAVE_STRCASECMP
+#define SDL_strcasecmp strcasecmp
+#elif defined(HAVE__STRICMP)
+#define SDL_strcasecmp _stricmp
+#else
 extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2);
+#endif
+
+#ifdef HAVE_STRNCASECMP
+#define SDL_strncasecmp strncasecmp
+#elif defined(HAVE__STRNICMP)
+#define SDL_strcasecmp _strnicmp
+#else
 extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen);
+#endif
+
+#ifdef HAVE_SSCANF
+#define SDL_sscanf sscanf
+#else
 extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, const char *fmt, ...);
+#endif
+
+#ifdef HAVE_SNPRINT
+#define SDL_snprintf snprintf
+#else
 extern DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...);
+#endif
+
+#ifdef HAVE_VSNPRINTF
+#define SDL_vsnprintf vsnprintf
+#else
 extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
+#endif
+
 
 /* taken from SDL2's zlib-licensed headers. */
 #define SDL_memset4(dst, val, dwords) do { \
@@ -139,9 +382,13 @@ extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char
     } \
   } while (0)
 
-/* sorry, you only get the heap. */
-#define SDL_stack_alloc(type, count)    (type*)SDL_malloc(sizeof(type)*(count))
-#define SDL_stack_free(data)            SDL_free(data)
+#ifdef HAVE_ALLOCA
+#define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count))
+#define SDL_stack_free(data)
+#else
+#define SDL_stack_alloc(type, count) (type*)SDL_malloc(sizeof(type)*(count))
+#define SDL_stack_free(data) SDL_free(data)
+#endif
 
 /* we're currently assuming you actually have these parts of the C runtime. Send patches if not. */
 #define SDL_abs abs
@@ -154,7 +401,13 @@ extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char
 #define SDL_tolower(X)  tolower(X)
 
 #define SDL_memcpy4(dst, src, len) SDL_memcpy(dst, src, (len) << 2)
+
+#ifdef HAVE_MEMMOVE
+#define SDL_memmove memmove
+#else
 #define SDL_memmove(dst, src, len) do { if ( dst < src ) { SDL_memcpy(dst, src, len); } else { SDL_revcpy(dst, src, len); } } while(0)
+#endif
+
 #define SDL_itoa(value, string, radix) SDL_ltoa((long)value, string, radix)
 #define SDL_uitoa(value, string, radix) SDL_ultoa((long)value, string, radix)
 #define SDL_atoi(X)     SDL_strtol(X, NULL, 0)