SDL: wikiheaders: Bind `#define`s below a function to it, like typedefs.

From 9f842e9b5a53e5ffed5487df06733d9a7e898f00 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 2 May 2024 12:49:30 -0400
Subject: [PATCH] wikiheaders: Bind `#define`s below a function to it, like
 typedefs.

This effectively adds the property symbols for various functions to the
function's wiki page.
---
 build-scripts/wikiheaders.pl | 54 ++++++++++++++++++++++++++++++++++++
 include/SDL3/SDL_audio.h     |  7 +++--
 include/SDL3/SDL_iostream.h  |  1 +
 include/SDL3/SDL_stdinc.h    |  2 ++
 4 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/build-scripts/wikiheaders.pl b/build-scripts/wikiheaders.pl
index 52272941b054b..8f922622bc583 100755
--- a/build-scripts/wikiheaders.pl
+++ b/build-scripts/wikiheaders.pl
@@ -780,6 +780,53 @@ sub print_undocumented_section {
                     $decl .= "\n";
                 }
             }
+
+            # !!! FIXME: code duplication with typedef processing, below.
+            # We assume any `#define`s directly after the function are related to it: probably bitflags for an integer typedef.
+            # We'll also allow some other basic preprocessor lines.
+            # Blank lines are allowed, anything else, even comments, are not.
+            my $blank_lines = 0;
+            my $lastpos = tell(FH);
+            my $lastlineno = $lineno;
+            my $additional_decl = '';
+            my $saw_define = 0;
+            while (<FH>) {
+                chomp;
+
+                $lineno++;
+
+                if (/\A\s*\Z/) {
+                    $blank_lines++;
+                } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) {
+                    if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) {
+                        $referenceonly{$1} = $sym;
+                        $saw_define = 1;
+                    } elsif (!$saw_define) {
+                        # if the first non-blank thing isn't a #define, assume we're done.
+                        seek(FH, $lastpos, 0);  # re-read eaten lines again next time.
+                        $lineno = $lastlineno;
+                        last;
+                    }
+
+                    # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text.
+                    if ($blank_lines > 0) {
+                        while ($blank_lines > 0) {
+                            $additional_decl .= "\n";
+                            push @decllines, '';
+                            $blank_lines--;
+                        }
+                    }
+                    $additional_decl .= "\n$_";
+                    push @decllines, $_;
+                    $lastpos = tell(FH);
+                } else {
+                    seek(FH, $lastpos, 0);  # re-read eaten lines again next time.
+                    $lineno = $lastlineno;
+                    last;
+                }
+            }
+            $decl .= $additional_decl;
+
         } elsif ($symtype == 2) {  # a macro
             if ($decl =~ /\A\s*\#\s*define\s+(.*?)(\(.*?\)|)\s+/) {
                 $sym = $1;
@@ -900,6 +947,7 @@ sub print_undocumented_section {
             my $lastpos = tell(FH);
             my $lastlineno = $lineno;
             my $additional_decl = '';
+            my $saw_define = 0;
             while (<FH>) {
                 chomp;
 
@@ -910,6 +958,12 @@ sub print_undocumented_section {
                 } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) {
                     if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) {
                         $referenceonly{$1} = $sym;
+                        $saw_define = 1;
+                    } elsif (!$saw_define) {
+                        # if the first non-blank thing isn't a #define, assume we're done.
+                        seek(FH, $lastpos, 0);  # re-read eaten lines again next time.
+                        $lineno = $lastlineno;
+                        last;
                     }
                     # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text.
                     if ($blank_lines > 0) {
diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h
index dd5296fd53a9a..e6ae924bcf931 100644
--- a/include/SDL3/SDL_audio.h
+++ b/include/SDL3/SDL_audio.h
@@ -1540,8 +1540,11 @@ extern DECLSPEC int SDLCALL SDL_LoadWAV_IO(SDL_IOStream * src, SDL_bool closeio,
 extern DECLSPEC int SDLCALL SDL_LoadWAV(const char *path, SDL_AudioSpec * spec,
                                         Uint8 ** audio_buf, Uint32 * audio_len);
 
-
-
+/**
+ * Maximum volume allowed in calls to SDL_MixAudioFormat.
+ *
+ * \since This macro is available since SDL 3.0.0.
+ */
 #define SDL_MIX_MAXVOLUME 128
 
 /**
diff --git a/include/SDL3/SDL_iostream.h b/include/SDL3/SDL_iostream.h
index 113ed5c87ff3f..d3f5c3e587cd1 100644
--- a/include/SDL3/SDL_iostream.h
+++ b/include/SDL3/SDL_iostream.h
@@ -375,6 +375,7 @@ extern DECLSPEC int SDLCALL SDL_CloseIO(SDL_IOStream *context);
  */
 extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *context);
 
+/* Possible `whence` values for SDL_IOStream seeking... */
 #define SDL_IO_SEEK_SET 0       /**< Seek from the beginning of data */
 #define SDL_IO_SEEK_CUR 1       /**< Seek relative to current read point */
 #define SDL_IO_SEEK_END 2       /**< Seek relative to the end of data */
diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h
index f079975893fa4..8a5db64daed50 100644
--- a/include/SDL3/SDL_stdinc.h
+++ b/include/SDL3/SDL_stdinc.h
@@ -2389,6 +2389,8 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode,
                                                const char *fromcode,
                                                const char *inbuf,
                                                size_t inbytesleft);
+
+/* Some helper macros for common cases... */
 #define SDL_iconv_utf8_locale(S)    SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1)
 #define SDL_iconv_utf8_ucs2(S)      (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)
 #define SDL_iconv_utf8_ucs4(S)      (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)