SDL: wikiheaders: updated from SDL3, plus fixes to headers to deal with that.

From 8b4e389ad07ba2431a3ce56b736a63e034c5663b Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 2 May 2024 13:00:03 -0400
Subject: [PATCH] wikiheaders: updated from SDL3, plus fixes to headers to deal
 with that.

---
 build-scripts/wikiheaders.pl | 151 ++++++++++++++++++++++++++++++++++-
 include/SDL_audio.h          |   3 +
 include/SDL_joystick.h       |   1 +
 include/SDL_rwops.h          |   1 +
 include/SDL_stdinc.h         |   3 +
 include/SDL_surface.h        |   5 +-
 include/SDL_system.h         |   8 +-
 7 files changed, 166 insertions(+), 6 deletions(-)

diff --git a/build-scripts/wikiheaders.pl b/build-scripts/wikiheaders.pl
index e03a306cefcd1..8f922622bc583 100755
--- a/build-scripts/wikiheaders.pl
+++ b/build-scripts/wikiheaders.pl
@@ -41,6 +41,7 @@
     $copy_direction = 1, next if $_ eq '--copy-to-header';
     $copy_direction = -1, next if $_ eq '--copy-to-wiki';
     $copy_direction = -2, next if $_ eq '--copy-to-manpages';
+    $copy_direction = -3, next if $_ eq '--report-coverage-gaps';
     if (/\A--options=(.*)\Z/) {
         $optionsfname = $1;
         next;
@@ -541,6 +542,21 @@ sub usage {
 my %wikisyms = ();  # contains references to hash of strings, each string being the full contents of a section of a wiki page, like $wikisyms{"SDL_OpenAudio"}{"Remarks"}.
 my %wikisectionorder = ();   # contains references to array, each array item being a key to a wikipage section in the correct order, like $wikisectionorder{"SDL_OpenAudio"}[2] == 'Remarks'
 
+my %referenceonly = ();  # $referenceonly{"Y"} -> symbol name that this symbol is bound to. This makes wiki pages that say "See X" where "X" is a typedef and "Y" is a define attached to it. These pages are generated in the wiki only and do not bridge to the headers or manpages.
+
+my @coverage_gap = ();  # array of strings that weren't part of documentation, or blank, or basic preprocessor logic. Lets you see what this script is missing!
+
+sub add_coverage_gap {
+    if ($copy_direction == -3) {  # --report-coverage-gaps
+        my $text = shift;
+        my $dent = shift;
+        my $lineno = shift;
+        return if $text =~ /\A\s*\Z/;  # skip blank lines
+        return if $text =~ /\A\s*\#\s*(if|el|endif|include)/; # skip preprocessor floof.
+        push @coverage_gap, "$dent:$lineno: $text";
+    }
+}
+
 sub print_undocumented_section {
     my $fh = shift;
     my $typestr = shift;
@@ -595,9 +611,11 @@ sub print_undocumented_section {
 
     my @contents = ();
     my $ignoring_lines = 0;
-
+    my $header_comment = -1;
+    my $lineno = 0;
     while (<FH>) {
         chomp;
+        $lineno++;
         my $symtype = 0;  # nothing, yet.
         my $decl;
         my @templines;
@@ -607,6 +625,12 @@ sub print_undocumented_section {
         # Since a lot of macros are just preprocessor logic spam and not all macros are worth documenting anyhow, we only pay attention to them when they have a Doxygen comment attached.
         # Functions and other things are a different story, though!
 
+        if ($header_comment == -1) {
+            $header_comment = /\A\/\*\s*\Z/ ? 1 : 0;
+        } elsif (($header_comment == 1) && (/\A\*\/\s*\Z/)) {
+            $header_comment = 0;
+        }
+
         if ($ignoring_lines && /\A\s*\#\s*endif\s*\Z/) {
             $ignoring_lines = 0;
             push @contents, $_;
@@ -632,17 +656,20 @@ sub print_undocumented_section {
             $has_doxygen = 0;
         } elsif (not /\A\/\*\*\s*\Z/) {  # not doxygen comment start?
             push @contents, $_;
+            add_coverage_gap($_, $dent, $lineno) if ($header_comment == 0);
             next;
         } else {   # Start of a doxygen comment, parse it out.
             @templines = ( $_ );
             while (<FH>) {
                 chomp;
+                $lineno++;
                 push @templines, $_;
                 last if /\A\s*\*\/\Z/;
                 if (s/\A\s*\*\s*\`\`\`/```/) {  # this is a hack, but a lot of other code relies on the whitespace being trimmed, but we can't trim it in code blocks...
                     $str .= "$_\n";
                     while (<FH>) {
                         chomp;
+                        $lineno++;
                         push @templines, $_;
                         s/\A\s*\*\s?//;
                         if (s/\A\s*\`\`\`/```/) {
@@ -659,6 +686,7 @@ sub print_undocumented_section {
             }
 
             $decl = <FH>;
+            $lineno++ if defined $decl;
             $decl = '' if not defined $decl;
             chomp($decl);
             if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC/) {
@@ -677,8 +705,10 @@ sub print_undocumented_section {
                 #print "Found doxygen but no function sig:\n$str\n\n";
                 foreach (@templines) {
                     push @contents, $_;
+                    add_coverage_gap($_, $dent, $lineno);
                 }
                 push @contents, $decl;
+                add_coverage_gap($decl, $dent, $lineno);
                 next;
             }
         }
@@ -693,6 +723,7 @@ sub print_undocumented_section {
                 if (not $decl =~ /\)\s*(\{.*|)\s*\Z/) {
                     while (<FH>) {
                         chomp;
+                        $lineno++;
                         push @decllines, $_;
                         s/\A\s+//;
                         s/\s+\Z//;
@@ -705,6 +736,7 @@ sub print_undocumented_section {
                 if (not $decl =~ /\)\s*;/) {
                     while (<FH>) {
                         chomp;
+                        $lineno++;
                         push @decllines, $_;
                         s/\A\s+//;
                         s/\s+\Z//;
@@ -748,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;
@@ -766,6 +845,7 @@ sub print_undocumented_section {
             while ($decl =~ /\\\Z/) {
                 my $l = <FH>;
                 last if not $l;
+                $lineno++;
                 chomp($l);
                 push @decllines, $l;
                 #$l =~ s/\A\s+//;
@@ -823,6 +903,7 @@ sub print_undocumented_section {
                     if (!$started || ($brackets != 0)) {
                         $pending = <FH>;
                         die("EOF/error reading $incpath/$dent while parsing $sym\n") if not $pending;
+                        $lineno++;
                         chomp($pending);
                         push @decllines, $pending;
                         $decl .= "\n";
@@ -858,6 +939,50 @@ sub print_undocumented_section {
                 }
                 next;
             }
+
+            # We assume any `#define`s directly after the typedef 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;
         } else {
             die("Unexpected symtype $symtype");
         }
@@ -1697,6 +1822,26 @@ sub print_undocumented_section {
         rename($path, "$wikipath/$_.${wikitype}") or die("Can't rename '$path' to '$wikipath/$_.${wikitype}': $!\n");
     }
 
+    # Write out simple redirector pages if they don't already exist.
+    foreach (keys %referenceonly) {
+        my $sym = $_;
+        my $refersto = $referenceonly{$sym};
+        my $path = "$wikipath/$sym.md";  # we only do Markdown for these.
+        next if (-f $path);  # don't overwrite if it already exists. Delete the file if you need a rebuild!
+        open(FH, '>', $path) or die("Can't open '$path': $!\n");
+
+        if (defined $wikipreamble) {
+            my $wikified_preamble = wikify('md', $wikipreamble);
+            print FH "###### $wikified_preamble\n";
+        }
+
+        print FH "# $sym\n\nPlease refer to [$refersto]($refersto) for details.\n\n";
+        #print FH "----\n";
+        #print FH "[CategoryAPI](CategoryAPI)\n\n";
+
+        close(FH);
+    }
+
     if (defined $readmepath) {
         if ( -d $readmepath ) {
             mkdir($wikireadmepath);  # just in case
@@ -2012,6 +2157,10 @@ sub print_undocumented_section {
         close(FH);
         rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n");
     }
+} elsif ($copy_direction == -3) { # --report-coverage_gaps
+    foreach (@coverage_gap) {
+        print("$_\n");
+    }
 }
 
 # end of wikiheaders.pl ...
diff --git a/include/SDL_audio.h b/include/SDL_audio.h
index cd401383690ce..e28dcbd5503ec 100644
--- a/include/SDL_audio.h
+++ b/include/SDL_audio.h
@@ -1122,6 +1122,9 @@ extern DECLSPEC void SDLCALL SDL_AudioStreamClear(SDL_AudioStream *stream);
  */
 extern DECLSPEC void SDLCALL SDL_FreeAudioStream(SDL_AudioStream *stream);
 
+/**
+ * Maximum volume allowed in calls to SDL_MixAudio and SDL_MixAudioFormat.
+ */
 #define SDL_MIX_MAXVOLUME 128
 
 /**
diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h
index 9d6ee92e70686..10be5dcbbf10d 100644
--- a/include/SDL_joystick.h
+++ b/include/SDL_joystick.h
@@ -807,6 +807,7 @@ extern DECLSPEC void SDLCALL SDL_JoystickUpdate(void);
  */
 extern DECLSPEC int SDLCALL SDL_JoystickEventState(int state);
 
+/* Limits for joystick axes... */
 #define SDL_JOYSTICK_AXIS_MAX   32767
 #define SDL_JOYSTICK_AXIS_MIN   -32768
 
diff --git a/include/SDL_rwops.h b/include/SDL_rwops.h
index 9d7665a70a760..b481a4b3c763f 100644
--- a/include/SDL_rwops.h
+++ b/include/SDL_rwops.h
@@ -366,6 +366,7 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_AllocRW(void);
  */
 extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area);
 
+/* Possible `whence` values for SDL_RWops seeking... */
 #define RW_SEEK_SET 0       /**< Seek from the beginning of data */
 #define RW_SEEK_CUR 1       /**< Seek relative to current read point */
 #define RW_SEEK_END 2       /**< Seek relative to the end of data */
diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h
index 3ebfed81b1742..63f01591c348b 100644
--- a/include/SDL_stdinc.h
+++ b/include/SDL_stdinc.h
@@ -528,6 +528,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_crc32(Uint32 crc, const void *data, size_t le
 
 extern DECLSPEC void *SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len);
 
+/* Some safe(r) macros for zero'ing structures... */
 #define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
 #define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
 #define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x)))
@@ -713,6 +714,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)
diff --git a/include/SDL_surface.h b/include/SDL_surface.h
index 2815844a18121..62fb8e28a4b22 100644
--- a/include/SDL_surface.h
+++ b/include/SDL_surface.h
@@ -927,8 +927,6 @@ extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface * src,
                                             const SDL_Rect * dstrect);
 
 
-#define SDL_BlitScaled SDL_UpperBlitScaled
-
 /**
  * Perform a scaled surface copy to a destination surface.
  *
@@ -943,6 +941,9 @@ extern DECLSPEC int SDLCALL SDL_UpperBlitScaled
     (SDL_Surface * src, const SDL_Rect * srcrect,
     SDL_Surface * dst, SDL_Rect * dstrect);
 
+#define SDL_BlitScaled SDL_UpperBlitScaled
+
+
 /**
  * Perform low-level surface scaled blitting only.
  *
diff --git a/include/SDL_system.h b/include/SDL_system.h
index 12c56fefa018e..e0216a7dfedc6 100644
--- a/include/SDL_system.h
+++ b/include/SDL_system.h
@@ -188,8 +188,6 @@ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID,
 /* Platform specific functions for iOS */
 #ifdef __IPHONEOS__
 
-#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam)
-
 /**
  * Use this function to set the animation callback on Apple iOS.
  *
@@ -224,7 +222,8 @@ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID,
  */
 extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (SDLCALL *callback)(void*), void *callbackParam);
 
-#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled)
+#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam)
+
 
 /**
  * Use this function to enable or disable the SDL event pump on Apple iOS.
@@ -242,6 +241,9 @@ extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window,
  */
 extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
 
+#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled)
+
+/* end of iOS-specific functions. */
 #endif /* __IPHONEOS__ */