SDL: wikiheaders.pl: Migrate in docs that exist only in the wiki.

From 3970a885a5589c7cd7212ed438153bb867208830 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 8 Oct 2021 14:39:28 -0400
Subject: [PATCH] wikiheaders.pl: Migrate in docs that exist only in the wiki.

This is going to expose some docs that needs cleaning up once
the bridge imports those docs, though.
---
 build-scripts/wikiheaders.pl | 117 ++++++++++++++++++++++-------------
 1 file changed, 75 insertions(+), 42 deletions(-)

diff --git a/build-scripts/wikiheaders.pl b/build-scripts/wikiheaders.pl
index 602b10939f..7c2411ad5d 100755
--- a/build-scripts/wikiheaders.pl
+++ b/build-scripts/wikiheaders.pl
@@ -292,6 +292,7 @@ sub usage {
 my %headerdecls = ();
 my %headerfuncslocation = ();   # $headerfuncslocation{"SDL_OpenAudio"} -> name of header holding SDL_OpenAudio define ("SDL_audio.h" in this case).
 my %headerfuncschunk = ();   # $headerfuncschunk{"SDL_OpenAudio"} -> offset in array in %headers that should be replaced for this function.
+my %headerfuncshasdoxygen = ();   # $headerfuncschunk{"SDL_OpenAudio"} -> 1 if there was no existing doxygen for this function.
 
 my $incpath = "$srcpath/include";
 opendir(DH, $incpath) or die("Can't opendir '$incpath': $!\n");
@@ -304,46 +305,54 @@ sub usage {
 
     while (<FH>) {
         chomp;
-        if (not /\A\/\*\*\s*\Z/) {  # not doxygen comment start?
+        my $decl;
+        my @templines;
+        my $str;
+        my $has_doxygen = 1;
+        if (/\A\s*extern\s+DECLSPEC/) {  # a function declaration without a doxygen comment?
+            @templines = ();
+            $decl = $_;
+            $str = '';
+            $has_doxygen = 0;
+        } elsif (not /\A\/\*\*\s*\Z/) {  # not doxygen comment start?
             push @contents, $_;
             next;
-        }
-
-        my @templines = ();
-        push @templines, $_;
-        my $str = '';
-        while (<FH>) {
-            chomp;
-            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;
-                    push @templines, $_;
-                    s/\A\s*\*\s?//;
-                    if (s/\A\s*\`\`\`/```/) {
-                        $str .= "$_\n";
-                        last;
-                    } else {
-                        $str .= "$_\n";
+        } else {   # Start of a doxygen comment, parse it out.
+            @templines = ( $_ );
+            while (<FH>) {
+                chomp;
+                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;
+                        push @templines, $_;
+                        s/\A\s*\*\s?//;
+                        if (s/\A\s*\`\`\`/```/) {
+                            $str .= "$_\n";
+                            last;
+                        } else {
+                            $str .= "$_\n";
+                        }
                     }
+                } else {
+                    s/\A\s*\*\s*//;
+                    $str .= "$_\n";
                 }
-            } else {
-                s/\A\s*\*\s*//;
-                $str .= "$_\n";
             }
-        }
 
-        my $decl = <FH>;
-        chomp($decl);
-        if (not $decl =~ /\A\s*extern\s+DECLSPEC/) {
-            #print "Found doxygen but no function sig:\n$str\n\n";
-            foreach (@templines) {
-                push @contents, $_;
+            $decl = <FH>;
+            $decl = '' if not defined $decl;
+            chomp($decl);
+            if (not $decl =~ /\A\s*extern\s+DECLSPEC/) {
+                #print "Found doxygen but no function sig:\n$str\n\n";
+                foreach (@templines) {
+                    push @contents, $_;
+                }
+                push @contents, $decl;
+                next;
             }
-            push @contents, $decl;
-            next;
         }
 
         my @decllines = ( $decl );
@@ -397,6 +406,7 @@ sub usage {
         $headerdecls{$fn} = $decl;
         $headerfuncslocation{$fn} = $dent;
         $headerfuncschunk{$fn} = scalar(@contents);
+        $headerfuncshasdoxygen{$fn} = $has_doxygen;
 
         push @contents, join("\n", @templines);
         push @contents, join("\n", @decllines);
@@ -522,7 +532,6 @@ sub usage {
 
     $wordwrap_mode = 'md';   # the headers use Markdown format.
 
-    # if it's not in the headers already, we don't add it, so iterate what we know is already there for changes.
     foreach (keys %headerfuncs) {
         my $fn = $_;
         next if not defined $wikifuncs{$fn};  # don't have a page for that function, skip it.
@@ -537,6 +546,8 @@ sub usage {
         my $addblank = 0;
         my $str = '';
 
+        $headerfuncshasdoxygen{$fn} = 1;  # Added/changed doxygen for this header.
+
         $brief = dewikify($wikitype, $brief);
         $brief =~ s/\A(.*?\.) /$1\n/;  # \brief should only be one sentence, delimited by a period+space. Split if necessary.
         my @briefsplit = split /\n/, $brief;
@@ -632,8 +643,15 @@ sub usage {
             }
         }
 
+        my $header = $headerfuncslocation{$fn};
+        my $contentsref = $headers{$header};
+        my $chunk = $headerfuncschunk{$fn};
+
         my @lines = split /\n/, $str;
-        my $output = "/**\n";
+
+        my $addnewline = (($chunk > 0) && ($$contentsref[$chunk-1] ne '')) ? "\n" : '';
+
+        my $output = "$addnewline/**\n";
         foreach (@lines) {
             chomp;
             s/\s*\Z//;
@@ -647,9 +665,6 @@ sub usage {
 
         #print("$fn:\n$output\n\n");
 
-        my $header = $headerfuncslocation{$fn};
-        my $chunk = $headerfuncschunk{$fn};
-        my $contentsref = $headers{$header};
         $$contentsref[$chunk] = $output;
         #$$contentsref[$chunk+1] = $headerdecls{$fn};
 
@@ -657,19 +672,36 @@ sub usage {
     }
 
     foreach (keys %changed_headers) {
-        my $contentsref = $headers{$_};
-        my $path = "$incpath/$_.tmp";
+        my $header = $_;
+
+        # this is kinda inefficient, but oh well.
+        my @removelines = ();
+        foreach (keys %headerfuncslocation) {
+            my $fn = $_;
+            next if $headerfuncshasdoxygen{$fn};
+            next if $headerfuncslocation{$fn} ne $header;
+            # the index of the blank line we put before the function declaration in case we needed to replace it with new content from the wiki.
+            push @removelines, $headerfuncschunk{$fn};
+        }
+
+        my $contentsref = $headers{$header};
+        foreach (@removelines) {
+            delete $$contentsref[$_];  # delete DOES NOT RENUMBER existing elements!
+        }
+
+        my $path = "$incpath/$header.tmp";
         open(FH, '>', $path) or die("Can't open '$path': $!\n");
         foreach (@$contentsref) {
-            print FH "$_\n";
+            print FH "$_\n" if defined $_;
         }
         close(FH);
-        rename($path, "$incpath/$_") or die("Can't rename '$path' to '$incpath/$_': $!\n");
+        rename($path, "$incpath/$header") or die("Can't rename '$path' to '$incpath/$header': $!\n");
     }
 
 } elsif ($copy_direction == -1) { # --copy-to-wiki
     foreach (keys %headerfuncs) {
         my $fn = $_;
+        next if not $headerfuncshasdoxygen{$fn};
         my $wikitype = defined $wikitypes{$fn} ? $wikitypes{$fn} : 'mediawiki';  # default to MediaWiki for new stuff FOR NOW.
         die("Unexpected wikitype '$wikitype'\n") if (($wikitype ne 'mediawiki') and ($wikitype ne 'md'));
 
@@ -678,6 +710,7 @@ sub usage {
         $wordwrap_mode = $wikitype;
 
         my $raw = $headerfuncs{$fn};  # raw doxygen text with comment characters stripped from start/end and start of each line.
+        next if not defined $raw;
         $raw =~ s/\A\s*\\brief\s+//;  # Technically we don't need \brief (please turn on JAVADOC_AUTOBRIEF if you use Doxygen), so just in case one is present, strip it.
 
         my @doxygenlines = split /\n/, $raw;